
#Область ОписаниеПеременных

&НаКлиенте
Перем ФормаОбщегоНазначения Экспорт; //см. ОбработкаОбъект.УИ_МенеджерОтрытыхФорм.ФормаОбщегоНазначения

#КонецОбласти

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	ЗаполнитьУсловноеОформление();
	
	ЗаполнитьКонстантыФормы();

	ЗаполнитьВспомогательныеЗначения();

	ЗаполнитьНастройкиПоУмолчанию();
	
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
	ЗаполнитьФормуОбщегоНазначения();
	
	ПрименитьНастройкиОбработки();
	
	НачатьОбновлениеОткрытыхФорм();
	
КонецПроцедуры

&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)

	Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") Тогда
		ПрименитьНастройкиОбработки(ВыбранноеЗначение);
	КонецЕсли;

КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовШапкиФормы

&НаКлиенте
Процедура ОткрытыеФормыНаходитсяВИзбранномНажатие(Элемент, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	ТекущиеДанные = Элементы.ОткрытыеФормы.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено ИЛИ ПустаяСтрока(ТекущиеДанные.НавигационнаяСсылка) Тогда
		Возврат;
	КонецЕсли;
	
	ДобавитьФормуВИзбранноеИлиУдалитьИзНего(ТекущиеДанные.НавигационнаяСсылка);
	ОбновитьИзбранныеСсылки(ВспомогательныеЗначения.ИзбранныеСсылки);
	ТекущиеДанные.НаходитсяВИзбранном = ФормаНаходитсяВИзбранном(ЭтотОбъект, ТекущиеДанные.НавигационнаяСсылка);
	ОбновитьИнтерфейс();
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыНавигационнаяСсылкаОткрытие(Элемент, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	ТекущиеДанные = Элементы.ОткрытыеФормы.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено ИЛИ ПустаяСтрока(ТекущиеДанные.НавигационнаяСсылка) Тогда
		Возврат;
	КонецЕсли;
	
	Попытка
		ПерейтиПоНавигационнойСсылке(ТекущиеДанные.НавигационнаяСсылка);
	Исключение
		СообщитьПользователю(ОписаниеОшибки());
	КонецПопытки;
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыНастройкиИзХранилищаНастройкиСтрокойВнутрОткрытие(Элемент, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	ТекущиеДанныеНастроек = Элементы.НастройкиИзХранилища.ТекущиеДанные;
	Если ТекущиеДанныеНастроек = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ПараметрыОткрываемойФормы = Новый Структура;
	ПараметрыОткрываемойФормы.Вставить("НастройкиСтрокойВнутр", ТекущиеДанныеНастроек.НастройкиСтрокойВнутр);
	
	ОткрытьФорму(ПолныйПутьКФормеОбработки("РедактированиеНастройкиИзХранилища"), ПараметрыОткрываемойФормы, Элемент);
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыНастройкиИзХранилищаНастройкиСтрокойВнутрОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
		
	ТекущиеДанныеНастроек = Элементы.НастройкиИзХранилища.ТекущиеДанные;
	Если ТекущиеДанныеНастроек = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Попытка
		СохранитьНастройкуФормыВХранилище(ТекущиеДанныеНастроек.КлючОбъекта,
			ТекущиеДанныеНастроек.КлючНастроек, ВыбранноеЗначение);
		ТекущиеДанныеНастроек.НастройкиСтрокойВнутр = ВыбранноеЗначение;
	Исключение
		СообщитьПользователю(ОписаниеОшибки());
	КонецПопытки;
	
КонецПроцедуры

&НаКлиенте
Процедура Реквизиты_ПроизвольныйРеквизитПриИзменении(Элемент)
	
	Реквизиты_ПроизвольныйРеквизит = СокрЛП(Реквизиты_ПроизвольныйРеквизит);
	ДополнитьИсториюПроверкиПроизвольногоРеквизитаТекущимЗначением();
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыОткрытыеФормы

&НаКлиенте
Процедура ОткрытыеФормыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	
	АктивизироватьТекущуюФорму();
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыОткрытыеФормыЭлементы

&НаКлиенте
Процедура ОткрытыеФормыЭлементыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	
	Если Поле = Элементы.ОткрытыеФормыЭлементыЗаголовок Тогда
		Возврат;
	КонецЕсли;
	
	Если Элемент.ТекущиеДанные <> Неопределено Тогда
		ТекущаяОткрытаяФорма = ТекущаяОткрытаяФорма();
		Если ТекущаяОткрытаяФорма <> Неопределено Тогда
			ТекущаяОткрытаяФорма.ТекущийЭлемент	= ТекущаяОткрытаяФорма.Элементы.Найти(Элемент.ТекущиеДанные.Имя);
		КонецЕсли;
		ТекущаяОткрытаяФорма.Активизировать();
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыЭлементыПриИзменении(Элемент)
	
	ОбновитьСвойствоОткрытойФормы("Элементы", Элемент.ТекущиеДанные);
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыЭлементыПоложениеЗаголовкаПриИзменении(Элемент)
	
	ТекущиеДанные = Элементы.ОткрытыеФормыЭлементы.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ПустаяСтрока(ТекущиеДанные.ПоложениеЗаголовка) Тогда
		ТекущиеДанные.ПоложениеЗаголовка = "Авто";
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыОткрытыеФормыРеквизиты

&НаКлиенте
Процедура ОткрытыеФормыРеквизитыПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные	= Элементы.ОткрытыеФормыРеквизиты.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	УстановитьСвойствоЭлемента(ЭтотОбъект, Элементы.ОткрытыеФормыРеквизитыЗначение,
		"ОграничениеТипа", ТекущиеДанные.ТипЗначения);
	УстановитьСвойствоЭлемента(ЭтотОбъект, Элементы.ОткрытыеФормыРеквизитыЗначение,
		"ТолькоПросмотр", ТекущиеДанные.ТолькоПросмотр);
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыРеквизитыПриИзменении(Элемент)
	
	ИзменитьЗначениеРеквизитаОткрытойФормы();
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыРеквизитыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	
	ОписаниеРеквизита = Элементы.ОткрытыеФормыРеквизиты.ТекущиеДанные;
	Если ОписаниеРеквизита = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	СтандартнаяОбработка = Ложь;
	
	Если ЗначениеЗаполнено(ОписаниеРеквизита.ТипЗначения.Типы()) Тогда
		ТипРеквизита = ОписаниеРеквизита.ТипЗначения;
	Иначе
		ЗначениеРеквизита = ЗначениеРеквизитаОткрытойФормы();
		ТекущиеТипы  = Новый Массив;
		ТекущиеТипы.Добавить(ТипЗнч(ЗначениеРеквизита));
		ТипРеквизита = Новый ОписаниеТипов(ТекущиеТипы);
	КонецЕсли;
	
	Если ТипРеквизита.СодержитТип(Тип("ДанныеФормыКоллекция"))
		ИЛИ ТипРеквизита.СодержитТип(Тип("ДанныеФормыДерево"))
		ИЛИ ТипРеквизита.СодержитТип(Тип("Структура"))
		ИЛИ ТипРеквизита.СодержитТип(Тип("ФиксированнаяСтруктура"))
		ИЛИ ТипРеквизита.СодержитТип(Тип("ФиксированноеСоответствие"))
		ИЛИ ТипРеквизита.СодержитТип(Тип("Соответствие")) Тогда
		
		ОткрытьЗначениеРеквизитаВРедакторе();
		
	ИначеЕсли ТипРеквизита.СодержитТип(Тип("КомпоновщикНастроекКомпоновкиДанных")) Тогда
		
		ОткрытьФормуНастроекКомпоновки();
		
	ИначеЕсли ТипРеквизита.СодержитТип(Тип("ДинамическийСписок")) Тогда
		
		ОткрытьФормуНастроекДинамическогоСписка();
		
	Иначе
		
		//@skip-check event-heandler-boolean-param - wtf?
		СтандартнаяОбработка = Истина;
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыОткрытыеФормыСвойства

&НаКлиенте
Процедура ОткрытыеФормыСвойстваПриИзменении(Элемент)
	
	ОбновитьСвойствоОткрытойФормы("Свойства", Элемент.ТекущиеДанные);
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыСвойстваВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	
	ТекущиеДанные = Элемент.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ТекущиеДанные.Свойство = "ТекущийЭлемент" Тогда
		
		СтандартнаяОбработка = Ложь;
		
		Попытка
			Элементы.ОткрытыеФормыЭлементы.ТекущаяСтрока = НайтиСтрокуЭлементаФормы(
				ЭтотОбъект, ТекущиеДанные.Значение).ПолучитьИдентификатор();
			Элементы.ОсновнаяГруппаПраво.ТекущаяСтраница = Элементы.ОсновнаяГруппаПраво_Элементы;
		Исключение
			СообщитьПользователю(ОписаниеОшибки());
		КонецПопытки;
		
	Иначе
		
		Возврат;
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыОткрытыеФормыПараметры

&НаКлиенте
Процедура ОткрытыеФормыПараметрыЗначениеПриИзменении(Элемент)

	УстановитьЗначениеПараметраОткрытойФормы();

КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормыПараметрыПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные = Элементы.ОткрытыеФормыПараметры.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	УстановитьСвойствоЭлемента(ЭтотОбъект, Элементы.ОткрытыеФормыПараметрыЗначение,
		"ОграничениеТипа", ТекущиеДанные.ТипЗначения);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыВыполнениеКода_Параметры

&НаКлиенте
Процедура ВыполнениеКода_ПараметрыПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
	
	ТекущиеДанные = Элемент.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ СтрокаВерногоФормата(ТекущиеДанные.Свойство) Тогда
		ТекстСообщения = "Имя свойства должно состоять из одного слова, " 
			+ "начинаться с буквы и не должно содержать специальных символов, кроме “_”";
		СообщитьПользователю(ТекстСообщения,,
			"ВыполнениеКода_Параметры[" + Элемент.ТекущаяСтрока + "].Свойство",, Отказ);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыНастройкиИзХранилища

&НаКлиенте
Процедура ОткрытыеФормыНастройкиИзХранилищаПередУдалением(Элемент, Отказ)
	
	Отказ = Истина;
	
	ТекущиеДанныеФормы      = Элементы.ОткрытыеФормы.ТекущиеДанные;
	ТекущиеДанныеНастройки  = Элементы.НастройкиИзХранилища.ТекущиеДанные;
	Если ТекущиеДанныеФормы = Неопределено ИЛИ ТекущиеДанныеНастройки = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ПараметрыВопроса	= Новый Структура;
	ПараметрыВопроса.Вставить("СтрокаФормы"     , ТекущиеДанныеФормы.ПолучитьИдентификатор());
	ПараметрыВопроса.Вставить("СтрокаНастройки"	, ТекущиеДанныеНастройки.ПолучитьИдентификатор());
	Вопрос_УдалитьНастройкуФормыИзХранилища(,ПараметрыВопроса);
	
КонецПроцедуры

&НаКлиенте
Процедура НастройкиИзХранилищаПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
	
	ПараметрыРедактированияНастройкиФормы = Новый Структура;
	
	Если Элемент.ТекущиеДанные = Неопределено Тогда
		СтарыеДанные = Неопределено;
	Иначе
		КлючиДанных = "КлючОбъекта,КлючОбъектаКраткий,КлючНастроек,НастройкиСтрокойВнутр";
		СтарыеДанные = Новый Структура(КлючиДанных);
		ЗаполнитьЗначенияСвойств(СтарыеДанные, Элемент.ТекущиеДанные);
	КонецЕсли;
	
	ПараметрыРедактированияНастройкиФормы.Вставить("СтарыеДанные", СтарыеДанные);
	
	ВспомогательныеЗначения.Вставить("ПараметрыРедактированияНастройкиФормы", ПараметрыРедактированияНастройкиФормы);
	
КонецПроцедуры

&НаКлиенте
Процедура НастройкиИзХранилищаПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
	
	ТекущиеДанныеФормы = Элементы.ОткрытыеФормы.ТекущиеДанные;
	ТекущиеДанныеНастройки = Элементы.НастройкиИзХранилища.ТекущиеДанные;
	Если ТекущиеДанныеФормы = Неопределено ИЛИ ТекущиеДанныеНастройки = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	СтарыеДанные = ВспомогательныеЗначения.ПараметрыРедактированияНастройкиФормы.СтарыеДанные;	
	
	Если ОтменаРедактирования Тогда
		
		Если НЕ НоваяСтрока Тогда
			ЗаполнитьЗначенияСвойств(ТекущиеДанныеНастройки, СтарыеДанные);
		КонецЕсли;
		
	Иначе
		
		Если ТекущиеДанныеФормы.НастройкиИзХранилища.НайтиСтроки(Новый Структура("КлючОбъектаКраткий,КлючНастроек",
			ТекущиеДанныеНастройки.КлючОбъектаКраткий,ТекущиеДанныеНастройки.КлючНастроек)).Количество()>1 Тогда
			
			СообщитьПользователю("Неуникальное значение КлючОбъекта\КлючНастроек!",,,,Отказ);
			
		Иначе
			
			Попытка
				СохраняемыйКлючОбъекта	= ТекущиеДанныеФормы.ИмяФормы + ТекущиеДанныеНастройки.КлючОбъектаКраткий;
				СохранитьНастройкуФормыВХранилище(СохраняемыйКлючОбъекта, 
					ТекущиеДанныеНастройки.КлючНастроек, ТекущиеДанныеНастройки.НастройкиСтрокойВнутр);
				Если НЕ НоваяСтрока И СтарыеДанные <> Неопределено Тогда
					УдалитьНастройкуФормыИзХранилища(СтарыеДанные.КлючОбъекта, СтарыеДанные.КлючНастроек);
				КонецЕсли;
				ТекущиеДанныеНастройки.КлючОбъекта = СохраняемыйКлючОбъекта;
			Исключение
				СообщитьПользователю(ОписаниеОшибки(),,,,Отказ);
			КонецПопытки;
			
		КонецЕсли;
		
	КонецЕсли;
	

КонецПроцедуры

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура Команда_ОбновитьОткрытыеФормы(Команда)
	
	НачатьОбновлениеОткрытыхФорм();
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОбновитьОткрытыеОкнаПоТаймеру(Команда)

	ОбновитьОткрытыеОкнаПоТаймеру();

КонецПроцедуры

&НаКлиенте
Процедура Команда_ВыполнитьПроизвольныйКод(Команда)
	
	Если ПустаяСтрока(ВыполнениеКода_ТекстНаКлиенте) Тогда
		Возврат;
	КонецЕсли;
	
	
	ДополнительныеПараметры	= Новый Структура;
	Для Каждого ДополнительныйПараметр Из ВыполнениеКода_Параметры Цикл
		ДополнительныеПараметры.Вставить(ДополнительныйПараметр.Свойство, ДополнительныйПараметр.Значение);
	КонецЦикла;
	
	
	ТекущаяОткрытаяФорма = ТекущаяОткрытаяФорма();
	ВыполнитьКодНаКлиенте(ТекущаяОткрытаяФорма, ВыполнениеКода_ТекстНаКлиенте,
		ВыполнениеКода_ТекстНаСервере, ДополнительныеПараметры);
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_УстановитьПроизвольноеСвойство(Команда)
	
	Если ПустаяСтрока(УстановкаПроизвольногоСвойства_Свойство) Тогда
		Возврат;
	КонецЕсли;
	
	ТекущаяОткрытаяФорма = ТекущаяОткрытаяФорма();
	Если ТекущаяОткрытаяФорма = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	НовоеЗначениеСвойства = УстановкаПроизвольногоСвойства_Значение;
	Если УстановкаПроизвольногоСвойства_ЭтоВыражение Тогда
		НовоеЗначениеСвойства = Вычислить(НовоеЗначениеСвойства);
	КонецЕсли;
	
	УстановитьСвойствоОбъекта(ТекущаяОткрытаяФорма, УстановкаПроизвольногоСвойства_Свойство, НовоеЗначениеСвойства);
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОбновитьДанныеОткрытойФормы(Команда)
	
	ТекущиеДанныеФормы = Элементы.ОткрытыеФормы.ТекущиеДанные;
	Если ТекущиеДанныеФормы <> Неопределено Тогда
		ОбновитьДанныеОткрытойФормы(ТекущиеДанныеФормы.УникальныйИдентификатор);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ВключитьВозможностьРедактирования(Команда)
	
	ВключитьВозможностьРедактированияФормы(ТекущаяОткрытаяФорма());
	АктивизироватьТекущуюФорму();
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ЗакрытьВыбраннуюФорму(Команда)
	
	ТекущаяФорма = ТекущаяОткрытаяФорма();
	Если ТекущаяФорма <> Неопределено Тогда
		УИД = ТекущаяФорма.УникальныйИдентификатор;
		ТекущаяФорма.Закрыть();
		ОбновитьДанныеОткрытойФормы(УИД);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_АктивизироватьТекущуюФорму(Команда)
	
	АктивизироватьТекущуюФорму();
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОткрытьСтраницуОбработки(Команда)
	
	ЗапуститьПриложение("https://infostart.ru/public/610324/?ref=1159");
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОткрытьФормуНастроекОбработки(Команда)
	
	ПараметрыОткрываемойФормы	= Новый Структура;
	Для Каждого ИмяРеквизита Из ВспомогательныеЗначения.РеквизитыНастроекФормы Цикл
		ПараметрыОткрываемойФормы.Вставить(ИмяРеквизита);
	КонецЦикла;
	ЗаполнитьЗначенияСвойств(ПараметрыОткрываемойФормы, ЭтотОбъект);
	
	ОткрытьФорму(ПолныйПутьКФормеОбработки("НастройкиОбработки"), ПараметрыОткрываемойФормы, ЭтотОбъект);
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОбновитьСвойстваВыбраннойФормы(Команда)
	
	СтрокаОткрытойФормы  = Элементы.ОткрытыеФормы.ТекущиеДанные;
	ТекущаяОткрытаяФорма = ТекущаяОткрытаяФорма();
	Если СтрокаОткрытойФормы = Неопределено ИЛИ ТекущаяОткрытаяФорма = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ОткрытыеФормы_Свойства_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы);
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОбновитьНастройкиИзХранилищаВыбраннойФормы(Команда)
	
	ТекущиеДанные = Элементы.ОткрытыеФормы.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ОбновитьСохраненныеНастройкиФормИзХранилища(ЭтотОбъект, ТекущиеДанные.ПолучитьИдентификатор());
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОбновитьДеревоЭлементов(Команда)
	
	СтрокаОткрытойФормы  = Элементы.ОткрытыеФормы.ТекущиеДанные;
	ТекущаяОткрытаяФорма = ТекущаяОткрытаяФорма();
	Если СтрокаОткрытойФормы = Неопределено ИЛИ ТекущаяОткрытаяФорма = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ДеревоЭлементов_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы);
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОткрытьВРедактореЗначений(Команда)
	
	ОткрытьЗначениеРеквизитаВРедакторе();
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ПроверитьНаличиеРеквизита(Команда)
	
	ПроверитьНаличиеРеквивизита(Реквизиты_ПроизвольныйРеквизит);
	
КонецПроцедуры
 
&НаКлиенте
Процедура Команда_ИзменитьРедакторомXML(Команда)
	
	ПараметрыФормыНастроек = Новый Структура;
	ПараметрыФормыНастроек.Вставить("Значение", ЗначениеРеквизитаОткрытойФормы());
	
	ОписаниеЗавершения = Новый ОписаниеОповещения("ПрименитьИзменениеРеквизитаВРедакторе", ЭтотОбъект);
	
	ОткрытьФорму(ПолныйПутьКФормеОбработки("ФормаРедакторXML"),
	ПараметрыФормыНастроек, ЭтотОбъект, Истина,,,ОписаниеЗавершения,РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	
КонецПроцедуры

&НаКлиенте
Процедура Команда_ОткрытьНовуюФорму(Команда)
	
	ОписаниеЗавершения = Новый ОписаниеОповещения("ОткрытьНовуюФорму", ЭтотОбъект);
	
	ОткрытьФорму(ПолныйПутьКФормеОбработки("ОткрытиеФормы"),
		Новый Структура("ВспомогательныеЗначения", ВспомогательныеЗначения),
		ЭтотОбъект,,,,ОписаниеЗавершения);
	
КонецПроцедуры


#КонецОбласти

#Область СлужебныеПроцедурыИФункции

#Область Инициализация

&НаСервере
Процедура ЗаполнитьУсловноеОформление()
	
	ЗаполнитьУсловноеОформление_Избранные();
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьУсловноеОформление_Избранные()
	
	ЭлементОформления = УсловноеОформление.Элементы.Добавить();
	ЭлементОформления.Использование = Истина;
	
	//@skip-check new-font - обработка не может зависить от конфигурации
	ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Шрифт", Новый Шрифт(,,Истина));
	
	ОформляемоеПоле = ЭлементОформления.Поля.Элементы.Добавить();
	ОформляемоеПоле.Использование = Истина;
	ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("ОткрытыеФормыЗаголовок1");
	
	ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбора.Использование = Истина;
	ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ОткрытыеФормы.НаходитсяВИзбранном");
	ЭлементОтбора.ПравоеЗначение = Истина;
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьНастройкиПоУмолчанию()
	
	УстановитьЗначениеНастройки(ЭтотОбъект, "РаботаСЭлементамиФорм", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "РаботаСоСвойствамиФорм", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "РаботаСРеквизитамиФорм", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "РаботаСКонсольюКода", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "ПоказыватьИсториюОткрытияФормы", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "ПоказыватьМенеджерОкон", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "ПоказыватьПараметрыФорм", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "РаботаСНастройкамиФорм", Истина);
	УстановитьЗначениеНастройки(ЭтотОбъект, "РаботаСПараметрамиФорм", Истина);
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьКонстантыФормы()
	
	ВыполнениеКода_ПодсказкаКонтекстКлиента = "ТекущаяФорма, ТекстНаСервере, ДополнительныеПараметры," 
		+ " ВыполнитьКодНаСервере(ТекстНаСервере, ДополнительныеПараметры)";
	ВыполнениеКода_ПодсказкаКонтекстСервера = "ДополнительныеПараметры";
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьВспомогательныеЗначения()
	
	СейОбъект	= РеквизитФормыВЗначение("Объект");
	ВспомогательныеЗначения = СейОбъект.НовыйВспомогательныеЗначения();
	
	ОбновитьИзбранныеСсылки(ВспомогательныеЗначения.ИзбранныеСсылки);
	
	ТипДекарацииФормы	= Тип("ДекорацияФормы");
	Для Каждого ЭлементФормы Из Элементы Цикл
		Если ТипЗнч(ЭлементФормы) <> ТипДекарацииФормы И ЭлементФормы.ОтображениеПодсказки = ОтображениеПодсказки.Кнопка Тогда
			ВспомогательныеЗначения.ЭлементыСКнопкамиПодсказки.Добавить(ЭлементФормы.Имя);
		КонецЕсли;
	КонецЦикла;
	
	Для Каждого РеквизитФормы Из ПолучитьРеквизиты() Цикл
		Если СтрНайти(РеквизитФормы.Имя, ВспомогательныеЗначения.ПриставкаРеквизитовНастроек) = 1 Тогда
			ВспомогательныеЗначения.РеквизитыНастроекФормы.Добавить(РеквизитФормы.Имя);
		КонецЕсли;
	КонецЦикла;
	
	Для Каждого РеквизитФормы Из ПолучитьРеквизиты("ОткрытыеФормы.Элементы") Цикл
		ВспомогательныеЗначения.СвойстваЭлементов.Добавить(РеквизитФормы.Имя);
	КонецЦикла;

	Для Каждого ТекущееПоложение Из ПоложениеЗаголовкаЭлементаФормы Цикл
		Элементы.ОткрытыеФормыЭлементыПоложениеЗаголовка.СписокВыбора.Добавить(Строка(ТекущееПоложение), Строка(ТекущееПоложение));
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьФормуОбщегоНазначения()
	
	ПолныйПутьФормы = ПолныйПутьКФормеОбработки("ОбщегоНазначения");
	ПараметрыПолучения = Новый Структура("ВспомогательныеЗначения", ВспомогательныеЗначения);
	//@skip-check use-non-recommended-method
	ФормаОбщегоНазначения = ПолучитьФорму(ПолныйПутьФормы, ПараметрыПолучения, ЭтотОбъект);
	
КонецПроцедуры

#КонецОбласти

#Область ОткрытыеФормы

&НаКлиенте
Процедура ОбновитьОткрытыеОкнаПоТаймеру(ИнтервалВремени = Null, ДополнительныеПараметры = Неопределено) Экспорт
	
	Если ИнтервалВремени = Null Тогда
		ПоказатьВводЧисла(
			Новый ОписаниеОповещения("ОбновитьОткрытыеОкнаПоТаймеру", ЭтотОбъект), 
			1, "Интервал времени в секундах с точностью до 1/10 секунды", 5, 1);
	ИначеЕсли ТипЗнч(ИнтервалВремени) = Тип("Число") Тогда
		ПодключитьОбработчикОжидания("НачатьОбновлениеОткрытыхФорм", ИнтервалВремени, Истина);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура НачатьОбновлениеОткрытыхФорм() Экспорт
	
	Элементы.ВерхниеСтраницы.ТекущаяСтраница = Элементы.СтраницаОжидание;
	ПодключитьОбработчикОжидания("ОбновитьОткрытыеФормы", 0.1, Истина);
	
КонецПроцедуры

&НаКлиенте
Функция ТекущаяОткрытаяФорма(ОписаниеФормы	= Неопределено)
	
	ТекущиеДанныеФормы = ?(ОписаниеФормы = Неопределено,Элементы.ОткрытыеФормы.ТекущиеДанные,ОписаниеФормы);
	
	Если ТекущиеДанныеФормы <> Неопределено Тогда
		Возврат ОткрытаяФормаПоУникальномуИдентификатору(ТекущиеДанныеФормы.УникальныйИдентификатор);
	КонецЕсли;
	
КонецФункции

&НаКлиенте
Процедура ОбновитьОткрытыеФормы()
	
	ОткрытыеФормы.Очистить();
	
	ВсеОткрытыеОкна = ПолучитьОкна();
	
	КоличествоОкон = ВсеОткрытыеОкна.Количество();
	
	НайденныеФормы = Новый Массив;
	Для ИндексОкна = 0 По КоличествоОкон-1 Цикл
		
		ТекущееОкно           = ВсеОткрытыеОкна[ИндексОкна];
		КоличествоСодержимого = ТекущееОкно.Содержимое.Количество();
		
		Для ИндексСодержимого = 0 По КоличествоСодержимого - 1 Цикл
			ТекущаяФорма = ТекущееОкно.Содержимое[ИндексСодержимого];
			Если ТипЗнч(ТекущаяФорма) = Тип("ФормаКлиентскогоПриложения") Тогда
				НайденныеФормы.Добавить(ТекущаяФорма);
			КонецЕсли;
		КонецЦикла;
		
	КонецЦикла;
	
	ВсегоНайденноФорм = НайденныеФормы.Количество();
	НомерТекущейФормы = 0;
	Для Каждого ТекущаяФорма Из НайденныеФормы Цикл
		НомерТекущейФормы = НомерТекущейФормы + 1;
		ТекстСостояния    = "Обновление информации о форме " + ТекущаяФорма.ИмяФормы;
		Состояние(ТекстСостояния, 
			Цел(НомерТекущейФормы/ВсегоНайденноФорм*100));
		ОбработкаПрерыванияПользователя();
		ОбновитьДанныеОткрытойФормы(ТекущаяФорма, Ложь, Ложь);
	КонецЦикла;
	
	Элементы.ВерхниеСтраницы.ТекущаяСтраница = Элементы.СтраницаОсновная;
	
	Если ОткрытыеФормы.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	ОбновитьСохраненныеНастройкиФормИзХранилища(ЭтотОбъект);
	ОбновитьИсториюОткрытияФорм(ЭтотОбъект);
	ОтсортироватьОткрытыеФормы(ЭтотОбъект);
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура ОтсортироватьОткрытыеФормы(Форма)
	
	Если НЕ ЗначениеНастройки(Форма, "СортироватьПоЗаголовкуФормы") Тогда
		Возврат;
	КонецЕсли;
	
	#Если Клиент Тогда
		Состояние("Сортировка открытых форм");
	#КонецЕсли
	
	СортироватьДанныеФормыКоллекция(Форма.ОткрытыеФормы, "Заголовок");
	
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьДанныеОткрытойФормы(КлючФормы, 
	ОбновлятьСохраненныеНастройки = Истина, ОбновлятьИсториюОткрытия = Истина)
	
	Если КлючФормы = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ТекущаяОткрытаяФорма = Неопределено;
	СтрокаОткрытойФормы  = Неопределено;
	УИДОткрытойФормы     = Неопределено;
	
	Если ТипЗнч(КлючФормы) = Тип("УникальныйИдентификатор") ИЛИ ТипЗнч(КлючФормы) = Тип("Строка") Тогда
		УИДОткрытойФормы     = Строка(КлючФормы);
		ТекущаяОткрытаяФорма = ОткрытаяФормаПоУникальномуИдентификатору(УИДОткрытойФормы);
	ИначеЕсли ТипЗнч(КлючФормы) = Тип("ФормаКлиентскогоПриложения") Тогда
		ТекущаяОткрытаяФорма = КлючФормы;
		УИДОткрытойФормы     = ТекущаяОткрытаяФорма.УникальныйИдентификатор;
	Иначе
		УИДОткрытойФормы     = КлючФормы.УникальныйИдентификатор;
		ТекущаяОткрытаяФорма = ОткрытаяФормаПоУникальномуИдентификатору(УИДОткрытойФормы);
	КонецЕсли;
	
	Если НЕ ЗначениеНастройки(ЭтотОбъект, "ПоказыватьМенеджерОкон") И ТекущаяОткрытаяФорма = ЭтотОбъект Тогда
		Возврат;
	КонецЕсли;
	
	СтрокаОткрытойФормы = ОткрытыеФормы.НайтиСтроки(
		Новый Структура("УникальныйИдентификатор", Строка(УИДОткрытойФормы)));
	
	Если ТекущаяОткрытаяФорма = Неопределено Тогда
		Если СтрокаОткрытойФормы.Количество() > 0 Тогда
			ОткрытыеФормы.Удалить(СтрокаОткрытойФормы[0]);
		КонецЕсли;
		Возврат;
	КонецЕсли;
	
	СтрокаОткрытойФормы = ?(СтрокаОткрытойФормы.Количество()=0,ОткрытыеФормы.Добавить(),СтрокаОткрытойФормы[0]);
	
	СтрокаОткрытойФормы.ТехническиеДанные = Новый Структура("Реквизиты");
	
	ЗаполнитьЗначенияСвойств(СтрокаОткрытойФормы, 
		ТекущаяОткрытаяФорма,"УникальныйИдентификатор,Заголовок,ИмяФормы,НавигационнаяСсылка");
	
	
	//Определяем картинку строки
	КлючВладельцаКартинки = "";
	Если ТекущаяОткрытаяФорма = ЭтотОбъект Тогда
		КлючВладельцаКартинки = "ЭтаФорма";
	ИначеЕсли СтрНайти(СтрокаОткрытойФормы.ИмяФормы, ".") > 0 Тогда
		КлючВладельцаКартинки = СтрРазделить(СтрокаОткрытойФормы.ИмяФормы, ".")[0];
	КонецЕсли;
	
	Если НЕ ПустаяСтрока(КлючВладельцаКартинки) Тогда
		ВспомогательныеЗначения.ИндексыКартинкиСтрокФорм.Свойство(КлючВладельцаКартинки, СтрокаОткрытойФормы.Картинка);
	КонецЕсли;
	
	ШаблонСообщенияОшибки = "[" + СтрокаОткрытойФормы.ИмяФормы + "] Не удалось получить %1 по причине: %2";
	
	//Сведения о форме
	Попытка
		ОткрытыеФормы_Сведения_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы);
	Исключение
		СообщитьПользователю(СтрШаблон(ШаблонСообщенияОшибки, "сведения", ОписаниеОшибки()));
	КонецПопытки;
	
	//Свойства формы	
	Попытка
		ОткрытыеФормы_Свойства_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы);
	Исключение
		СообщитьПользователю(СтрШаблон(ШаблонСообщенияОшибки, "свойства", ОписаниеОшибки()));
	КонецПопытки;
	
	//Элементы формы
	Попытка
		ДеревоЭлементов_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы);
	Исключение
		СообщитьПользователю(СтрШаблон(ШаблонСообщенияОшибки, "элементы", ОписаниеОшибки()));
	КонецПопытки;
	
	//Реквизиты формы
	Попытка
		ДеревоРеквизитов_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы);
	Исключение
		СообщитьПользователю(СтрШаблон(ШаблонСообщенияОшибки, "реквизиты", ОписаниеОшибки()));
	КонецПопытки;
		
	
	//Параметры формы
	Попытка
		ОбновитьПараметрыОткрытойФормы(СтрокаОткрытойФормы, ТекущаяОткрытаяФорма);
	Исключение
		СообщитьПользователю(СтрШаблон(ШаблонСообщенияОшибки, "параметры", ОписаниеОшибки()));
	КонецПопытки;
	
	//Настройки из хранилища
	Если ОбновлятьСохраненныеНастройки Тогда
		Попытка
			ОбновитьСохраненныеНастройкиФормИзХранилища(ЭтотОбъект, СтрокаОткрытойФормы);
		Исключение
			СообщитьПользователю(СтрШаблон(ШаблонСообщенияОшибки, "сохраненные настройки", ОписаниеОшибки()));
		КонецПопытки;
	КонецЕсли;
	
	//История открытия формы
	Если ОбновлятьИсториюОткрытия Тогда
		Попытка
			ОбновитьИсториюОткрытияФормы(ЭтотОбъект, СтрокаОткрытойФормы);
		Исключение
			СообщитьПользователю(СтрШаблон(ШаблонСообщенияОшибки, "историю", ОписаниеОшибки()));
		КонецПопытки;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция ФормаНаходитсяВИзбранном(Форма, НавигационнаяСсылкаФормы)
	
	Возврат Форма.ВспомогательныеЗначения.ИзбранныеСсылки.Найти(НавигационнаяСсылкаФормы) <> Неопределено;
	
КонецФункции

&НаКлиенте
Процедура АктивизироватьТекущуюФорму()
	
	ТекущаяОткрытаяФорма = ТекущаяОткрытаяФорма();
	
	Если ТекущаяОткрытаяФорма <> Неопределено Тогда
		ТекущаяОткрытаяФорма.Активизировать();
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ДобавитьФормуВИзбранноеИлиУдалитьИзНего(НавигационнаяСсылка)
	
	Если ПустаяСтрока(НавигационнаяСсылка) Тогда
		Возврат;
	КонецЕсли;
	
	Избранное = ХранилищеСистемныхНастроек.Загрузить("Общее/ИзбранноеРаботыПользователя");
	Если Избранное = Неопределено Тогда
		Избранное = Новый ИзбранноеРаботыПользователя;
	КонецЕсли;
	
	ЭлементИзбранного = Неопределено;
	Для Каждого ТекЭлементИзбранного Из Избранное Цикл
		Если ТекЭлементИзбранного.НавигационнаяСсылка = НавигационнаяСсылка Тогда
			ЭлементИзбранного = ТекЭлементИзбранного;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	
	Если ЭлементИзбранного = Неопределено Тогда
		ЭлементИзбранного = Новый ЭлементИзбранногоРаботыПользователя;
		ЭлементИзбранного.НавигационнаяСсылка	= НавигационнаяСсылка;
		Избранное.Добавить(ЭлементИзбранного);
	Иначе
		Избранное.Удалить(Избранное.Индекс(ЭлементИзбранного));
	КонецЕсли;
	
	
	ХранилищеСистемныхНастроек.Сохранить("Общее/ИзбранноеРаботыПользователя",,Избранное);
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура ВключитьВозможностьРедактированияФормы(Форма)
	
	Если Форма = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	НовыеЗначения = Новый Структура("ТолькоПросмотр,Доступность",Ложь,Истина);
	ЗаполнитьЗначенияСвойств(Форма, НовыеЗначения);	
	Для Каждого ЭлементФормы Из Форма.Элементы Цикл
		Если ТипЗнч(ЭлементФормы) <> Тип("ДекорацияФормы") Тогда
			ЗаполнитьЗначенияСвойств(ЭлементФормы, НовыеЗначения);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласти

#Область ДеревоЭлементов

&НаКлиенте
Процедура ДеревоЭлементов_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, Сортировать = Истина)
	
	СтрокаОткрытойФормы.Элементы.ПолучитьЭлементы().Очистить();
	
	Если НЕ ЗначениеНастройки(ЭтотОбъект, "РаботаСЭлементамиФорм") Тогда
		Возврат;
	КонецЕсли;
	
	ПрототипДерева = ДеревоЭлементов_Прототип(ТекущаяОткрытаяФорма);
	
	ДеревоЭлементов_ЗаполнитьИзПрототипа(ТекущаяОткрытаяФорма, ПрототипДерева, СтрокаОткрытойФормы.Элементы.ПолучитьЭлементы());
	
	ДеревоЭлементов_Отсортировать(ЭтотОбъект, ОткрытыеФормы.Индекс(СтрокаОткрытойФормы));
		
КонецПроцедуры

&НаКлиенте
Процедура ДеревоЭлементов_ЗаполнитьИзПрототипа(ТекущаяОткрытаяФорма, ПрототипДерева, КоллекцияЭлементовДерева)
	
	ПорядковыйНомерЭлемента = 0;
	
	Для Каждого КлючИЗначение Из ПрототипДерева Цикл
		
		ПорядковыйНомерЭлемента = ПорядковыйНомерЭлемента + 1;
		
		ТекущийЭлементФормы = ТекущаяОткрытаяФорма.Элементы.Найти(КлючИЗначение.Ключ);
		Если ТекущийЭлементФормы = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		
		СписокИсключаемыхСвойств	= "";
		ИндексКартинки				= 0;
		ПриоритетСортировки			= 100 + ПорядковыйНомерЭлемента;
		ТипТекущегоЭлемента			= ТипЗнч(ТекущийЭлементФормы);
		Если ТипТекущегоЭлемента = Тип("ГруппаФормы") Тогда
			ТипРодителяЭлемента		= ТипЗнч(ТекущийЭлементФормы.Родитель);
			РодительПолеФормы		= ТипРодителяЭлемента = Тип("ПолеФормы");
			РодительТаблицаФормы	= ТипРодителяЭлемента = Тип("ТаблицаФормы");
			РодительСамаФорма		= ТипРодителяЭлемента = Тип("ФормаКлиентскогоПриложения");
			ВидТекущегоЭлемента		= ТекущийЭлементФормы.Вид;
			Если ВидТекущегоЭлемента = ВидГруппыФормы.КонтекстноеМеню 
				ИЛИ ((РодительПолеФормы ИЛИ РодительТаблицаФормы) И ТекущийЭлементФормы.Родитель.КонтекстноеМеню = ТекущийЭлементФормы) Тогда
				ИндексКартинки		= 3;
				ПриоритетСортировки	= 2;
			ИначеЕсли ВидТекущегоЭлемента = ВидГруппыФормы.КоманднаяПанель
				ИЛИ ((РодительТаблицаФормы ИЛИ РодительСамаФорма) И ТекущийЭлементФормы.Родитель.КоманднаяПанель = ТекущийЭлементФормы) Тогда
				ИндексКартинки		= 1;
				ПриоритетСортировки	= 1;
			Иначе
				ИндексКартинки	= 7;
			КонецЕсли;
		ИначеЕсли ТипТекущегоЭлемента = Тип("ТаблицаФормы") Тогда
			ИндексКартинки	= 2;
		ИначеЕсли ТипТекущегоЭлемента = Тип("ПолеФормы") Тогда
			ИндексКартинки	= 5;
		ИначеЕсли ТипТекущегоЭлемента = Тип("КнопкаФормы") Тогда
			ИндексКартинки	= 8;
		ИначеЕсли ТипТекущегоЭлемента = Тип("ДекорацияФормы") Тогда
			СписокИсключаемыхСвойств	= "Видимость,Доступность";
			Если ТипЗнч(ТекущийЭлементФормы.Родитель) <> Тип("ФормаКлиентскогоПриложения") 
				И ТекущийЭлементФормы.Родитель.РасширеннаяПодсказка = ТекущийЭлементФормы Тогда
				ИндексКартинки		= 4;
				ПриоритетСортировки	= 3;
			Иначе
				ИндексКартинки		= 6;
			КонецЕсли;
		ИначеЕсли ТипТекущегоЭлемента = Тип("ДополнениеЭлементаФормы") Тогда
			ВидТекущегоЭлемента	= ТекущийЭлементФормы.Вид;
			Если ВидТекущегоЭлемента = ВидДополненияЭлементаФормы.ОтображениеСтрокиПоиска Тогда
				ИндексКартинки		= 10;
				ПриоритетСортировки	= 4;
			ИначеЕсли ВидТекущегоЭлемента = ВидДополненияЭлементаФормы.ОтображениеСостоянияПросмотра Тогда
				ИндексКартинки		= 11;
				ПриоритетСортировки	= 5;
			ИначеЕсли ВидТекущегоЭлемента = ВидДополненияЭлементаФормы.УправлениеПоиском Тогда
				ИндексКартинки		= 12;
				ПриоритетСортировки	= 6;
			КонецЕсли;
		КонецЕсли;
		
		ТипЭлемента			= ВспомогательныеЗначения.ТипыЭлементовПоИндексуКартинки.Получить(ИндексКартинки);
		
		СтрокаДерева	= КоллекцияЭлементовДерева.Добавить();
		ЗаполнитьЗначенияСвойств(СтрокаДерева, ТекущийЭлементФормы, , СписокИсключаемыхСвойств);
		СтрокаДерева.ИндексКартинки			= ИндексКартинки;
		СтрокаДерева.ПриоритетСортировки	= ПриоритетСортировки;
		СтрокаДерева.ТипЭлемента			= ТипЭлемента;
		
		ДеревоЭлементов_ЗаполнитьИзПрототипа(ТекущаяОткрытаяФорма, КлючИЗначение.Значение, СтрокаДерева.ПолучитьЭлементы());
		
	КонецЦикла;
	
		
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура ДеревоЭлементов_Отсортировать(Форма, ИндексСтрокиОтрытойФормы = Неопределено)
	
	Если ИндексСтрокиОтрытойФормы = Неопределено Тогда
		КоллекцияОткрытыхФорм	= Форма.ОткрытыеФормы;
	Иначе
		КоллекцияОткрытыхФорм	= Новый Массив;
		КоллекцияОткрытыхФорм.Добавить(Форма.ОткрытыеФормы.Получить(ИндексСтрокиОтрытойФормы));
	КонецЕсли;
	
	Для Каждого СтрокаОткрытойФормы Из КоллекцияОткрытыхФорм Цикл
		СортироватьДанныеФормыДерево(СтрокаОткрытойФормы.Элементы, "ПриоритетСортировки", Истина);
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Функция ДеревоЭлементов_Прототип(ТекущаяОткрытаяФорма)
	
	ПрототипДерева	= Новый Структура;
	Для Каждого ЭлементФормы Из ТекущаяОткрытаяФорма.Элементы Цикл
		ДеревоЭлементов_Прототип_ДобавитьБезопасно(ПрототипДерева, ЭлементФормы);
	КонецЦикла;
	
	Возврат ПрототипДерева;
	
КонецФункции

&НаКлиенте
Функция ДеревоЭлементов_Прототип_ДобавитьБезопасно(ПрототипДерева, ЭлементФормы)
	
	ИмяЭлемента      = ЭлементФормы.Имя;
	РодительЭлемента = ЭлементФормы.Родитель;
	
	Если ТипЗнч(РодительЭлемента) = Тип("ФормаКлиентскогоПриложения") Тогда
		РодительВПрототипе = ПрототипДерева;
	Иначе
		РодительВПрототипе = ДеревоЭлементов_Прототип_ДобавитьБезопасно(ПрототипДерева, РодительЭлемента);
	КонецЕсли;
	
	Если НЕ РодительВПрототипе.Свойство(ИмяЭлемента) Тогда
		РодительВПрототипе.Вставить(ИмяЭлемента, Новый Структура);
	КонецЕсли;
	
	Возврат РодительВПрототипе[ИмяЭлемента];
		
КонецФункции

#КонецОбласти

#Область Свойства

&НаКлиенте
Процедура ОбновитьСвойстваОткрытыхФорм()
	
	Для Каждого СтрокаОткрытойФормы Из ОткрытыеФормы Цикл
		
		ТекущаяОткрытаяФорма = ОткрытаяФормаПоУникальномуИдентификатору(СтрокаОткрытойФормы.УникальныйИдентификатор);
		Если ТекущаяОткрытаяФорма = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		ОткрытыеФормы_Свойства_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы);
		
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытыеФормы_Свойства_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы)
	
	СтрокаОткрытойФормы.Свойства.Очистить();
	
	Если НЕ ЗначениеНастройки(ЭтотОбъект, "РаботаСоСвойствамиФорм") Тогда
		Возврат;
	КонецЕсли;
	
	ОткрытыеФормы_Свойства_Добавить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы.Свойства, "АвтоЗаголовок");
	ОткрытыеФормы_Свойства_Добавить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы.Свойства, "Доступность");
	ОткрытыеФормы_Свойства_Добавить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы.Свойства, "Заголовок");
	ОткрытыеФормы_Свойства_Добавить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы.Свойства, "Модифицированность");
	ОткрытыеФормы_Свойства_Добавить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы.Свойства, "ТолькоПросмотр");
	
	//@skip-check bsl-legacy-check-string-literal - ОсновнойЭлементФормы - недокументированный тип, который нужно проверять
	Если НЕ ТекущаяОткрытаяФорма.ТекущийЭлемент = Неопределено
		И НЕ ТипЗнч(ТекущаяОткрытаяФорма.ТекущийЭлемент) = Тип("ОсновнойЭлементФормы") Тогда
		ОткрытыеФормы_Свойства_Добавить(ТекущаяОткрытаяФорма, 
			СтрокаОткрытойФормы.Свойства, "ТекущийЭлемент", ТекущаяОткрытаяФорма.ТекущийЭлемент.Имя);
	КонецЕсли;
		
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция ОткрытыеФормы_Свойства_Добавить(ТекущаяФорма, Свойства, Свойство, Значение = Null)
	
	Если Значение = Null Тогда
		Значение	= ТекущаяФорма[Свойство];
	КонецЕсли;
	
	МассивТипов	= Новый Массив;
	МассивТипов.Добавить(ТипЗнч(Значение));
	ТипЗначения	= Новый ОписаниеТипов(МассивТипов);
	
	ОписаниеСвойства = Свойства.Добавить();
	ОписаниеСвойства.Свойство     = Свойство;
	ОписаниеСвойства.ТипЗначения  = ТипЗначения;
	ОписаниеСвойства.Значение     = Значение;
	
	Возврат ОписаниеСвойства;
	
КонецФункции

&НаКлиенте
Процедура ОткрытыеФормы_Сведения_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы)
	
	Если ТекущаяОткрытаяФорма.Окно <> Неопределено Тогда
		СтрокаОткрытойФормы.Заголовок = ТекущаяОткрытаяФорма.Окно.Заголовок;
	КонецЕсли;
	
	Если НЕ ТекущаяОткрытаяФорма.Параметры = Неопределено Тогда
		ТекущаяОткрытаяФорма.Параметры.Свойство("Ключ", СтрокаОткрытойФормы.Ключ);
	КонецЕсли;
	
	СтрокаОткрытойФормы.НавигационнаяСсылка = ПолучитьНавигационнуюСсылку(ТекущаяОткрытаяФорма);
	СтрокаОткрытойФормы.НаходитсяВИзбранном = ФормаНаходитсяВИзбранном(
		ЭтотОбъект, СтрокаОткрытойФормы.НавигационнаяСсылка);
	
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьСвойствоОткрытойФормы(ТипСвойств, ОписаниеСвойства)
	
	
	Если ОписаниеСвойства = Неопределено Тогда
		Возврат;
	КонецЕсли;
		
	ОписаниеФормы = Элементы.ОткрытыеФормы.ТекущиеДанные;
	Если ОписаниеФормы = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ОткрытаяФормы = ОткрытаяФормаПоУникальномуИдентификатору(ОписаниеФормы.УникальныйИдентификатор);
	Если ОткрытаяФормы = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ТипСвойств = "Свойства" Тогда
		
		ОткрытаяФормы[ОписаниеСвойства.Свойство]	= ОписаниеСвойства.Значение;
		
	ИначеЕсли ТипСвойств = "Элементы" Тогда
		
		НовыеСвойстваЭлемента = СтруктураИзОписанияЭлементаФормы(ЭтотОбъект, ОписаниеСвойства);
		
		Если ПустаяСтрока(НовыеСвойстваЭлемента.ПоложениеЗаголовка) Тогда
			НовыеСвойстваЭлемента.Удалить("ПоложениеЗаголовка");
		Иначе
			НовыеСвойстваЭлемента.ПоложениеЗаголовка	= ПоложениеЗаголовкаЭлементаФормы[ОписаниеСвойства.ПоложениеЗаголовка];
		КонецЕсли;
		
		ЭлементОткрытойФормы = ОткрытаяФормы.Элементы.Найти(ОписаниеСвойства.Имя);
		Если ТипЗнч(ЭлементОткрытойФормы) = Тип("ДекорацияФормы") Тогда
			НовыеСвойстваЭлемента.Удалить("Видимость");
			НовыеСвойстваЭлемента.Удалить("Доступность");
		КонецЕсли;
		
		ЗаполнитьЗначенияСвойств(ЭлементОткрытойФормы, НовыеСвойстваЭлемента);
		
	КонецЕсли;
	
	ОткрытыеФормы_Сведения_Заполнить(ОткрытаяФормы, ОписаниеФормы);
	
КонецПроцедуры

#КонецОбласти

#Область ПараметрыФормы

&НаКлиенте
Процедура ОбновитьПараметрыОткрытойФормы(ОписаниеФормы = Неопределено, ОткрытаяФорма = Неопределено)
    
    #Если ВебКлиент Тогда 
        Возврат;    //TODO: Нужно доработать под веб-клиент
    #КонецЕсли
    Если НЕ ЗначениеНастройки(ЭтотОбъект, "РаботаСПараметрамиФорм") Тогда
        Возврат;
    КонецЕсли;
    
    Если ОписаниеФормы = Неопределено Тогда
		ОписаниеФормы = Элементы.ОткрытыеФормы.ТекущиеДанные;
	КонецЕсли;
	Если ОткрытаяФорма = Неопределено Тогда
		ОткрытаяФорма = ТекущаяОткрытаяФорма(ОписаниеФормы);
	КонецЕсли;
	
	Если ОписаниеФормы = Неопределено ИЛИ ОткрытаяФорма = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ПараметрыВОписании = ОписаниеФормы.Параметры;
	ПараметрыВОписании.Очистить();
    
    Для Каждого КлючИЗначение Из СтруктураИзПараметровФормы(ОткрытаяФорма.Параметры) Цикл
		ОписаниеПараметра = ПараметрыВОписании.Добавить();
		ЗаполнитьЗначенияСвойств(ОписаниеПараметра, КлючИЗначение);
		ОписаниеПараметра.ТипЗначения = Новый ОписаниеТипов(ЗначениеВМассиве(ТипЗнч(КлючИЗначение.Значение)));
	КонецЦикла;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция СтруктураИзПараметровФормы(ПараметрыФормы)
	
	Если ТипЗнч(ПараметрыФормы) = Тип("Структура") Тогда
		Возврат ПараметрыФормы;
	ИначеЕсли ПараметрыФормы = Неопределено Тогда
		Возврат Новый Структура;
	КонецЕсли;
    
    #Если ВебКлиент Тогда
        
        Возврат СтруктураИзПараметровФормыДляВебКлиента(ПараметрыФормы);
        
    #Иначе
        
    	СтруктураРезультат = Новый Структура;
        
        СтрокаXML   = ЗначениеВСтрокуXML(ПараметрыФормы);
    	ЧтениеXML   = Новый ЧтениеXML;
    	ЧтениеXML.УстановитьСтроку(СтрокаXML);
    	
    	Пока ЧтениеXML.Прочитать() Цикл
    		
    		Если ЧтениеXML.Имя = "structure" 
    			И ЧтениеXML.ПолучитьАтрибут("name") = "parameters" 
    			И ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
    			
    			Прервать;
    			             
    		ИначеЕсли ЧтениеXML.Имя = "field" Тогда
    			
    			ТекущийКлюч	= ЧтениеXML.ПолучитьАтрибут("nameRu");
    			ТекущийКлюч	= ?(ЗначениеЗаполнено(ТекущийКлюч), ТекущийКлюч, ЧтениеXML.ПолучитьАтрибут("name"));
    			Если ЗначениеЗаполнено(ТекущийКлюч) Тогда
    				СтруктураРезультат.Вставить(ТекущийКлюч);
    			КонецЕсли;
    			
    		КонецЕсли;
    		
    	КонецЦикла;
    	
    	ЧтениеXML.Закрыть();
    	
    	ЗаполнитьЗначенияСвойств(СтруктураРезультат, ПараметрыФормы);
    	
    	Возврат СтруктураРезультат;
    
    #КонецЕсли
	
КонецФункции

&НаСервереБезКонтекста
Функция СтруктураИзПараметровФормыДляВебКлиента(Знач ПараметрыФормы)
	
	Возврат СтруктураИзПараметровФормы(ПараметрыФормы);
	
КонецФункции

&НаКлиенте
Процедура УстановитьЗначениеПараметраОткрытойФормы(ОписаниеПараметра = Неопределено)
    
    Если ОписаниеПараметра = Неопределено Тогда
        ОписаниеПараметра   = Элементы.ОткрытыеФормыПараметры.ТекущиеДанные;
        Если ОписаниеПараметра = Неопределено Тогда
            Возврат;
        КонецЕсли;
    КонецЕсли;
    
    ОткрытаяФорма   = ТекущаяОткрытаяФорма();
    Если ОткрытаяФорма = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ОткрытаяФорма.Параметры[ОписаниеПараметра.Ключ] = ОписаниеПараметра.Значение;
    
КонецПроцедуры
	
#КонецОбласти

#Область Реквизиты

&НаКлиенте
Процедура ДеревоРеквизитов_Заполнить(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы)
		   
	Если НЕ ЗначениеНастройки(ЭтотОбъект, "РаботаСРеквизитамиФорм") Тогда
		Возврат;
	КонецЕсли;
	
	СтрокаОткрытойФормы.Реквизиты.ПолучитьЭлементы().Очистить();

	СтрокаОткрытойФормы.ТехническиеДанные.Реквизиты = Новый Соответствие;
	
	Для Каждого ТекущееИмя Из СтрРазделить("Объект,Запись,Отчет", ",") Цикл
		ТекущееЗначение		= Неопределено;
		Если СвойствоОбъекта(ТекущаяОткрытаяФорма, ТекущееИмя, ТекущееЗначение) Тогда
			ДобавитьОписаниеРеквизитаСПодчиненными(
			ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, 
			ТекущееИмя, ТекущееЗначение);
		КонецЕсли;
	КонецЦикла;
	
	
	Для Каждого ТекущийЭлементФормы Из ТекущаяОткрытаяФорма.Элементы Цикл
		
		ТекущееЗначение = Неопределено;
		ТекущееИмя = ТекущийЭлементФормы.Имя;
		
		Если СвойствоОбъекта(ТекущаяОткрытаяФорма, ТекущееИмя, ТекущееЗначение) Тогда
			ДобавитьОписаниеРеквизитаСПодчиненными(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, ТекущееИмя, ТекущееЗначение);
		КонецЕсли;
		
	КонецЦикла;
	
	ВозможныеРодители = Новый Массив;
	Для Каждого КореннойРеквизитФормы Из СтрокаОткрытойФормы.Реквизиты.ПолучитьЭлементы() Цикл
		Если КореннойРеквизитФормы.ТипЗначения.СодержитТип(Тип("ДанныеФормыСтруктура")) Тогда
			ВозможныеРодители.Добавить(КореннойРеквизитФормы);
		КонецЕсли;
	КонецЦикла;
	
	Для Каждого ВозможныйРодитель Из ВозможныеРодители Цикл
		Для Каждого ТекущийЭлементФормы Из ТекущаяОткрытаяФорма.Элементы Цикл
			ТекущееИмя = ТекущийЭлементФормы.Имя;
			ТекущееЗначение = Неопределено;
			Если СвойствоОбъекта(ТекущаяОткрытаяФорма[ВозможныйРодитель.Имя], ТекущееИмя, ТекущееЗначение) Тогда
				ДобавитьОписаниеРеквизитаСПодчиненными(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, ТекущееИмя, ТекущееЗначение, ВозможныйРодитель,,Истина);
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
		
	ЗаполнитьРеквизитыФормыРазборомДанныхФормы(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, ВозможныеРодители);
	
	Для Каждого ТекущийПроверяемыйРеквизит Из ЗначениеНастройки(ЭтотОбъект, "АвтоматическиПроверяемыеРеквизиты") Цикл
		ПроверитьНаличиеРеквивизита(ТекущийПроверяемыйРеквизит.Значение, СтрокаОткрытойФормы);
	КонецЦикла;
	
КонецПроцедуры

//TODO: поправить
//@skip-check method-too-many-params - 
&НаКлиенте
Функция ДобавитьОписаниеРеквизитаСПодчиненными(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, 
	ИмяРеквизита, ИсточникОпределенияПодчиненныхСвойств, РодительРеквизита = Неопределено, 
	ТолькоПросмотрРеквизита = Ложь, ПроверятьНаличиеРеквизита = Истина, ОписаниеТиповРеквизита = Неопределено)
	
	ОписаниеРеквизитовЗначения = ОписаниеРеквизитовЗначения(ЭтотОбъект, ИсточникОпределенияПодчиненныхСвойств);
	
	КоллекцияРеквизитов = ?(РодительРеквизита = Неопределено, СтрокаОткрытойФормы.Реквизиты, РодительРеквизита);
	
	ОписаниеРеквизита = ДеревоРеквизитов_Добавить(СтрокаОткрытойФормы, КоллекцияРеквизитов, ИмяРеквизита, 
	ИсточникОпределенияПодчиненныхСвойств, ОписаниеТиповРеквизита, 
	ОписаниеРеквизитовЗначения.ТолькоПросмотр ИЛИ ТолькоПросмотрРеквизита, ПроверятьНаличиеРеквизита);
		
	Для Каждого КлючИЗначение Из ОписаниеРеквизитовЗначения.Реквизиты Цикл
		
		ТекущееИмя = КлючИЗначение.Ключ;
		ТекущийТип = ТипЗнч(КлючИЗначение.Значение); //TODO: ???
		ТекущееЗначение = Неопределено;
		
		ДобавлятьРеквизит = Ложь;
		
		Если РодительРеквизита = Неопределено Тогда
			ДобавлятьРеквизит = СвойствоОбъекта(ТекущаяОткрытаяФорма[ИмяРеквизита], ТекущееИмя, ТекущееЗначение);
		Иначе
			ДобавлятьРеквизит = ВложенноеСвойствоОбъектаВПопытке(
			ТекущаяОткрытаяФорма[РодительРеквизита.Имя], ИмяРеквизита + "." + ТекущееИмя, ТекущееЗначение);
		КонецЕсли;
		
		Если ДобавлятьРеквизит Тогда
			Если ОписаниеРеквизитовЗначения.ВыводитьПодчиненные Тогда
				ДобавитьОписаниеРеквизитаСПодчиненными(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы,
				ТекущееИмя, ТекущееЗначение, ОписаниеРеквизита, 
				ОписаниеРеквизитовЗначения.ТолькоПросмотрПодчиненных, ПроверятьНаличиеРеквизита, ТекущийТип);
			Иначе
				ДеревоРеквизитов_Добавить(СтрокаОткрытойФормы, ОписаниеРеквизита, ТекущееИмя, ТекущееЗначение, ТекущийТип, 
				ОписаниеРеквизитовЗначения.ТолькоПросмотрПодчиненных,ПроверятьНаличиеРеквизита);
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат ОписаниеРеквизита;
	
КонецФункции

&НаКлиенте
Функция ДеревоРеквизитов_Добавить(СтрокаОткрытойФормы, Родитель, ИмяРеквизита, ЗначениеРеквизита, 
	ТипЗначения = Неопределено, ТолькоПросмотрЗначения = Ложь, ПроверятьНаличиеРеквизита = Ложь)
	
	
	Если Родитель = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	КэшРеквизитов = СтрокаОткрытойФормы.ТехническиеДанные.Реквизиты;
	
	КоллекцияРеквизитов = Родитель.ПолучитьЭлементы();
	
	Если ТипЗнч(Родитель)=Тип("ДанныеФормыЭлементДерева") Тогда
		ПолныйПутьРеквизита = СтрШаблон("%1.%2", Родитель.ПолныйПуть, ИмяРеквизита);
	Иначе
		ПолныйПутьРеквизита = ИмяРеквизита;
	КонецЕсли;
	
	Если ПроверятьНаличиеРеквизита Тогда
		ОписаниеРеквизита = КэшРеквизитов.Получить(ПолныйПутьРеквизита);
		Если НЕ ОписаниеРеквизита = Неопределено Тогда
			//TODO: !!!Нужно получить из идентификатора
			Возврат СтрокаОткрытойФормы.Реквизиты.НайтиПоИдентификатору(ОписаниеРеквизита);
		КонецЕсли;
	КонецЕсли;
	
	ОписаниеРеквизита = КоллекцияРеквизитов.Добавить();
	ОписаниеРеквизита.Имя = ИмяРеквизита;
	ОписаниеРеквизита.ТолькоПросмотр = ТолькоПросмотрЗначения;
	ОписаниеРеквизита.ПолныйПуть = ПолныйПутьРеквизита;
	
	Если ТипЗначения = Неопределено Тогда
		ОписаниеРеквизита.ТипЗначения = Новый ОписаниеТипов(ЗначениеВМассиве(ТипЗнч(ЗначениеРеквизита)));
	Иначе
		ОписаниеРеквизита.ТипЗначения = ТипЗначения;
	КонецЕсли;
	
	Попытка
		ОписаниеРеквизита.Значение = ЗначениеРеквизита;
	Исключение
		ОписаниеРеквизита.Значение = Строка(ЗначениеРеквизита);
		ОписаниеРеквизита.ТолькоПросмотр= Истина;
	КонецПопытки;
	
	КэшРеквизитов.Вставить(ПолныйПутьРеквизита, ОписаниеРеквизита.ПолучитьИдентификатор());
	
	Возврат ОписаниеРеквизита;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ОписаниеРеквизитовЗначения(Форма, Значение, ЗначениеИзКэша = Истина)
	
	КэшОписаний        = Форма.ВспомогательныеЗначения.КэшОписанийРеквизитовПоТипам;	
	ТипЗначения        = ТипЗнч(Значение);
	ОписаниеРеквизитов = Неопределено;
	
	Если ЗначениеИзКэша Тогда
		
		ОписаниеРеквизитов = КэшОписаний.Получить(ТипЗначения);
		Если ОписаниеРеквизитов = Неопределено Тогда
			ОписаниеРеквизитов = ОписаниеРеквизитовЗначения(Форма, Значение, Ложь);
		КонецЕсли;
		
	Иначе
		
		КлючКэшаОписания   = ТипЗначения;
		КлючКэшаОписания = Неопределено; //TODO: Временно отключаем кэширование - работает со сбоями
		
		ОписаниеРеквизитов = Новый Структура;
		ОписаниеРеквизитов.Вставить("ВыводитьПодчиненные"      , Истина);
		ОписаниеРеквизитов.Вставить("ТолькоПросмотр"           , Ложь);
		ОписаниеРеквизитов.Вставить("ТолькоПросмотрПодчиненных", Ложь);
		ОписаниеРеквизитов.Вставить("Реквизиты", Новый Структура);
		
		Если ТипЗначения = Тип("ДинамическийСписок") Тогда
			
			КлючиСвойств = "АвтоматическоеСохранениеПользовательскихНастроек,Группировка,
			|КлючТекущихПользовательскихНастроек,КомпоновщикНастроек,Отбор,Параметры,Порядок,УсловноеОформление";
			ОписаниеРеквизитов.Реквизиты = Новый Структура(КлючиСвойств);
			
		ИначеЕсли ТипЗначения = Тип("КомпоновщикНастроекКомпоновкиДанных") Тогда
			
			ОписаниеРеквизитов.Реквизиты = Новый Структура("Настройки");
			
		ИначеЕсли ТипЗначения = Тип("Структура")
			ИЛИ ТипЗначения = Тип("ФиксированнаяСтруктура") Тогда
			
			ОписаниеРеквизитов.ТолькоПросмотр      = Истина;
			ОписаниеРеквизитов.ВыводитьПодчиненные = Истина;
			ОписаниеРеквизитов.Реквизиты = Значение;
			
		ИначеЕсли ТипЗначения = Тип("Соответствие")
			ИЛИ ТипЗначения = Тип("ФиксированноеСоответствие") Тогда
			
			ОписаниеРеквизитов.ТолькоПросмотр      = Истина;
			ОписаниеРеквизитов.ВыводитьПодчиненные = Ложь;
			
		ИначеЕсли ТипЗначения = Тип("ДанныеФормыСтруктура") Тогда
			
			ОписаниеРеквизитов.ТолькоПросмотр      = Истина;
			ОписаниеРеквизитов.ВыводитьПодчиненные = Ложь;
			
			Если Значение.Свойство("Ссылка") Тогда
				ТипЗначенияСтруктуры = ТипЗнч(Значение.Ссылка);
			ИначеЕсли Значение.Свойство("ИсходныйКлючЗаписи") Тогда
				ТипЗначенияСтруктуры = ТипЗнч(Значение.ИсходныйКлючЗаписи);
			Иначе
				ТипЗначенияСтруктуры = Тип("Неопределено");
			КонецЕсли;
			
			Если НЕ ТипЗначенияСтруктуры = Тип("Неопределено") Тогда
				ОписаниеРеквизитов.Реквизиты	= РеквизитыПоТипу(Форма, ТипЗначенияСтруктуры);
			КонецЕсли;
			
			КлючКэшаОписания = Неопределено;
			
		КонецЕсли;
		
		Если НЕ КлючКэшаОписания = Неопределено Тогда
			КэшОписаний.Вставить(КлючКэшаОписания, ОписаниеРеквизитов);
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат ОписаниеРеквизитов;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция РеквизитыПоТипу(Форма, ТипЗначения, ЗначениеИзКэша = Истина)
	
	КэшОписаний     = Форма.ВспомогательныеЗначения.КэшРеквизитовПоТипам;	
	
	НаборРеквизитов = Неопределено;
	
	Если ЗначениеИзКэша Тогда
		
		НаборРеквизитов = КэшОписаний.Получить(ТипЗначения);
		Если НаборРеквизитов = Неопределено Тогда
			НаборРеквизитов = РеквизитыПоТипу(Форма, ТипЗначения, Ложь);
		КонецЕсли;
		
	Иначе
		
		НаборРеквизитов = ОписаниеРеквизитовПоТипуНаСервере(ТипЗначения);
		
	КонецЕсли;
	
	Возврат НаборРеквизитов;
	
КонецФункции

&НаСервереБезКонтекста
Функция ОписаниеРеквизитовПоТипуНаСервере(ТипЗначения)
	
	ОписаниеРеквизитов = Новый Структура;
	
	МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗначения);
	Если НЕ МетаданныеОбъекта = Неопределено Тогда
		КлючиСвойств = "СтандартныеРеквизиты,Измерения,Ресурсы,Реквизиты";
		Для Каждого КлючИЗначение Из Новый Структура(КлючиСвойств) Цикл
			ТекущаяКоллекция = Неопределено;
			Если СвойствоОбъекта(МетаданныеОбъекта, КлючИЗначение.Ключ, ТекущаяКоллекция) Тогда
				Для Каждого ТекущийЭлемент Из ТекущаяКоллекция Цикл
					ОписаниеРеквизитов.Вставить(ТекущийЭлемент.Имя, ТекущийЭлемент.Тип);
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат ОписаниеРеквизитов;
	
КонецФункции

&НаКлиенте
Процедура ИзменитьЗначениеРеквизитаОткрытойФормы(ОписаниеФормы = Неопределено, 
	ОписаниеРеквизита = Неопределено, ЗначениеРеквизита = Null)
	
	Если ОписаниеРеквизита = Неопределено Тогда
		ОписаниеРеквизита = Элементы.ОткрытыеФормыРеквизиты.ТекущиеДанные;
	КонецЕсли;
	Если ОписаниеФормы = Неопределено Тогда
		ОписаниеФормы = Элементы.ОткрытыеФормы.ТекущиеДанные;
	КонецЕсли;
	Если ОписаниеФормы = Неопределено ИЛИ ОписаниеРеквизита = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ОткрытаяФорма	= ОткрытаяФормаПоУникальномуИдентификатору(ОписаниеФормы.УникальныйИдентификатор);
	
	ЗначениеРеквизита	= ?(ЗначениеРеквизита=Null, ОписаниеРеквизита.Значение, ЗначениеРеквизита);
	ТекущееЗначениеРеквизита = ЗначениеРеквизитаОткрытойФормы(ОписаниеФормы, ОписаниеРеквизита, ОткрытаяФорма);
	
	
	
	Если ТипЗнч(ЗначениеРеквизита) = Тип("ДанныеФормыКоллекция") 
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("ДинамическийСписок") 
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("ОтборКомпоновкиДанных")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("ПорядокКомпоновкиДанных")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("УсловноеОформлениеКомпоновкиДанных")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("ЗначенияПараметровДанныхКомпоновкиДанных")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("ПоляГруппировкиКомпоновкиДанных")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("КомпоновщикНастроекКомпоновкиДанных") Тогда

		ЗагружатьЗначение = Истина;
		ОбновитьРеквизиты = Ложь;
		
	ИначеЕсли ТипЗнч(ТекущееЗначениеРеквизита) = Тип("Структура")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("ФиксированнаяСтруктура")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("Соответствие")
		ИЛИ ТипЗнч(ТекущееЗначениеРеквизита) = Тип("ФиксированноеСоответствие") Тогда
		
		ЗагружатьЗначение = Истина;
		ОбновитьРеквизиты = Истина;
		
	Иначе
		
		ЗагружатьЗначение = Ложь;
		ОбновитьРеквизиты = Ложь;
		
	КонецЕсли;
	
	Если ЗагружатьЗначение Тогда
		ВыполняемыйСкрипт = "ЗагрузитьЗначение(ОткрытаяФорма.%1, ЗначениеРеквизита);";
	Иначе
		ВыполняемыйСкрипт = "ОткрытаяФорма.%1 = ЗначениеРеквизита;";
	КонецЕсли;
	
	ВыполняемыйСкрипт = СтрШаблон(ВыполняемыйСкрипт, ОписаниеРеквизита.ПолныйПуть);
	
	#Если ВебКлиент Тогда
		
		//TODO: Исправить
		ВызватьИсключение "Неподдерживается в веб клиенте!";
	
	#Иначе
		
		Попытка
			Выполнить(ВыполняемыйСкрипт);
		Исключение
			СообщитьПользователю(ОписаниеОшибки());
		КонецПопытки;
		
	#КонецЕсли
	
	ВложенноеСвойствоОбъектаВПопытке(ОткрытаяФорма, ОписаниеРеквизита.ПолныйПуть, ОписаниеРеквизита.Значение);
	Для Каждого ПодчиненныйРеквизит Из ОписаниеРеквизита.ПолучитьЭлементы() Цикл
		ВложенноеСвойствоОбъектаВПопытке(ОткрытаяФорма, ПодчиненныйРеквизит.ПолныйПуть, ПодчиненныйРеквизит.Значение);
	КонецЦикла;
	
	Если ОбновитьРеквизиты Тогда
		
		ТекущийПуть = ОписаниеРеквизита.ПолныйПуть;
		
		ДеревоРеквизитов_Заполнить(ОткрытаяФорма, ОписаниеФормы);
		
		Попытка
			Элементы.ОткрытыеФормыРеквизиты.ТекущаяСтрока = ДанныеФормыКоллекцияЭлементовДереваНайтиСтроки(
			ОписаниеФормы.Реквизиты.ПолучитьЭлементы(), 
			Новый Структура("ПолныйПуть", ТекущийПуть), Истина)[0].ПолучитьИдентификатор();
		Исключение
			СообщитьПользователю(ОписаниеОшибки());
		КонецПопытки;
		
	КонецЕсли;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
// Назаренко_СВ 2017-05-22
//
// Аналог метода НайтиСтроки коллекции строк дерева значений, используемый в случае использования дерева значений в управляемых формах.
//
//Параметры:
// КоллекцияСтрок – ДанныеФормыКоллекцияЭлементовДерева – Коллекция подчиненных строк элемента дерева значений, используемого в управляемых формах.
// ПараметрыОтбора - Структура - Структура с критериями поиска.
//                               Задает условия поиска: ключ структуры определяет имя колонки, по которой будет осуществляться поиск,
//                               а значение структуры - искомое значение.
//                               Структура без полей означает "выбрать все подчиненные строки".
// ВключатьПодчиненные - Булево - Определяет, будет ли производиться поиск также в подчиненных коллекциях (если таковые имеются).
//                                Истина - поиск будет произведен.
//
//Возвращаемое значение:
// Массив(ДанныеФормыЭлементДерева) – Массив из строк дерева значений, соответствующих заданному условию поиска.
//
Функция ДанныеФормыКоллекцияЭлементовДереваНайтиСтроки(КоллекцияСтрок, ПараметрыОтбора, ВключатьПодчиненные = Ложь)
	Результат = Новый Массив;
	Для Каждого СтрокаТекущая Из КоллекцияСтрок Цикл
		СтрокаНайдена = Истина;
		Для Каждого КлючИЗначение Из ПараметрыОтбора Цикл
			Если СтрокаТекущая[КлючИЗначение.Ключ] <> КлючИЗначение.Значение Тогда
				СтрокаНайдена = Ложь;
				Прервать;
			КонецЕсли;
		КонецЦикла;
		Если СтрокаНайдена Тогда
			Результат.Добавить(СтрокаТекущая);
		КонецЕсли;
		Если ВключатьПодчиненные Тогда
			ПодчиненныеСтроки = ДанныеФормыКоллекцияЭлементовДереваНайтиСтроки(СтрокаТекущая.ПолучитьЭлементы(), ПараметрыОтбора, ВключатьПодчиненные);
			Для Каждого НайденнаяСтрока Из ПодчиненныеСтроки Цикл
				Результат.Добавить(НайденнаяСтрока);
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
КонецФункции

&НаКлиенте
Функция ЗначениеРеквизитаОткрытойФормы(ОписаниеФормы = Неопределено, ОписаниеРеквизита = Неопределено, ОткрытаяФорма = Неопределено)
	
	Если ОписаниеРеквизита = Неопределено Тогда
		ОписаниеРеквизита = Элементы.ОткрытыеФормыРеквизиты.ТекущиеДанные;
	КонецЕсли;
	Если ОписаниеФормы = Неопределено Тогда
		ОписаниеФормы = Элементы.ОткрытыеФормы.ТекущиеДанные;
	КонецЕсли;
	Если ОписаниеФормы = Неопределено ИЛИ ОписаниеРеквизита = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если ОткрытаяФорма = Неопределено Тогда
		ОткрытаяФорма = ОткрытаяФормаПоУникальномуИдентификатору(ОписаниеФормы.УникальныйИдентификатор);
	КонецЕсли;
	
	Попытка
		ЗначениеРеквизита = Вычислить("ОткрытаяФорма." + ОписаниеРеквизита.ПолныйПуть);
	Исключение
		ЗначениеРеквизита = Неопределено;
	КонецПопытки;
	
	Возврат ЗначениеРеквизита;
	
КонецФункции

&НаКлиенте
Процедура ОткрытьЗначениеРеквизитаВРедакторе(ЗначениеРеквизита = Неопределено)
	
	Если ЗначениеРеквизита = Неопределено Тогда
		ЗначениеРеквизита = ЗначениеРеквизитаОткрытойФормы();
	КонецЕсли;
	
	ТипЗначения = ТипЗнч(ЗначениеРеквизита);
	Если ТипЗначения = Тип("Структура") 
		ИЛИ ТипЗначения = Тип("Соответствие")
		ИЛИ ТипЗначения = Тип("ФиксированнаяСтруктура")
		ИЛИ ТипЗначения = Тип("ФиксированноеСоответствие") Тогда
		
		ПараметрыРедактора = Новый Структура();
		ПараметрыРедактора.Вставить("РедактируемоеЗначение", ЗначениеРеквизита);
		
		ОткрытьФорму(ПолныйПутьКФормеОбработки("РедакторСтруктурыСоответствия"), ПараметрыРедактора, ЭтотОбъект, , , , 
		Новый ОписаниеОповещения("ПрименитьИзменениеРеквизитаВРедакторе", ЭтотОбъект), РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
		
	Иначе
		
		ПараметрыРедактора = Новый Структура();
		ПараметрыРедактора.Вставить("ПроизвольныеЗначения", Новый Структура);
		ПараметрыРедактора.ПроизвольныеЗначения.Вставить("ЗначениеРеквизита", ЗначениеРеквизита);
		
		ОткрытьФорму(ПолныйПутьКФормеОбработки("РедакторПроизвольныхЗначений"), ПараметрыРедактора, ЭтотОбъект, , , , 
		Новый ОписаниеОповещения("ПрименитьИзменениеРеквизитаВРедакторе", ЭтотОбъект), РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
		
	КонецЕсли;
	
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура ЗагрузитьЗначение(Значение, НовоеЗначение)
	
	Если ТипЗнч(Значение) = Тип("ДинамическийСписок") Тогда
		ЗагрузитьЗначение(Значение.КомпоновщикНастроек, НовоеЗначение);
	ИначеЕсли ТипЗнч(Значение) = Тип("КомпоновщикНастроекКомпоновкиДанных") Тогда
		Значение.ЗагрузитьНастройки(НовоеЗначение.Настройки);
		Значение.ЗагрузитьФиксированныеНастройки(НовоеЗначение.ФиксированныеНастройки);
		Значение.ЗагрузитьПользовательскиеНастройки(НовоеЗначение.ПользовательскиеНастройки);
	ИначеЕсли ТипЗнч(Значение) = Тип("ДанныеФормыКоллекция") Тогда
		КопироватьДанныеФормы(НовоеЗначение,Значение);
	ИначеЕсли ТипЗнч(Значение) = Тип("Структура") 
		ИЛИ ТипЗнч(Значение) = Тип("ФиксированнаяСтруктура")
		ИЛИ ТипЗнч(Значение) = Тип("ФиксированноеСоответствие")
		ИЛИ ТипЗнч(Значение) = Тип("Соответствие") Тогда
		
		ЗаполнитьСтруктуруСоответствиеРекурсивно(Значение, НовоеЗначение);
		УдалитьОтстутствуюшиеКлючи(Значение, НовоеЗначение)
			
	ИначеЕсли ТипЗнч(Значение) = Тип("ОтборКомпоновкиДанных")
		ИЛИ ТипЗнч(Значение) = Тип("ПорядокКомпоновкиДанных")
		ИЛИ ТипЗнч(Значение) = Тип("УсловноеОформлениеКомпоновкиДанных")
		ИЛИ ТипЗнч(Значение) = Тип("ЗначенияПараметровДанныхКомпоновкиДанных")
		ИЛИ ТипЗнч(Значение) = Тип("ПоляГруппировкиКомпоновкиДанных") Тогда
		СкопироватьЭлементыНастроек(Значение, НовоеЗначение);
	КонецЕсли;
	
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура УдалитьОтстутствуюшиеКлючи(Коллекция, КоллекцияПроверки)
	
	Если ТипЗнч(Коллекция) = Тип("Структура") Тогда
		ЭтоСтруктура = Истина;
	ИначеЕсли ТипЗнч(Коллекция) = Тип("Соответствие") Тогда
		ЭтоСтруктура = Ложь;
	Иначе
		Возврат;
	КонецЕсли;
	
	МассивУдаляемых = Новый Массив;
	
	Для Каждого КлючИЗначение Из Коллекция Цикл
		
		ТекущийКлюч = КлючИЗначение.Ключ;
		ТекущееЗначение = КлючИЗначение.Значение;
		УдалитьКлюч = Истина;
		ЗначениеИзПроверки = Неопределено;
		
		Если ЭтоСтруктура Тогда
			
			Если КоллекцияПроверки.Свойство(ТекущийКлюч, ЗначениеИзПроверки) Тогда
				УдалитьКлюч = Ложь;
			КонецЕсли;
			
		Иначе
			
			ЗначениеИзПроверки = КоллекцияПроверки.Получить(ТекущийКлюч);
			Если ЗначениеИзПроверки <> Неопределено Тогда
				УдалитьКлюч = Ложь;
			КонецЕсли;
			
		КонецЕсли;
		
		Если УдалитьКлюч Тогда
			МассивУдаляемых.Добавить(ТекущийКлюч);
		ИначеЕсли ТипЗнч(ТекущееЗначение) = ТипЗнч(ЗначениеИзПроверки)
			И ТипЗнч(ТекущееЗначение) = Тип("Структура") 
			ИЛИ ТипЗнч(ТекущееЗначение) = Тип("Соответствие") Тогда
			УдалитьОтстутствуюшиеКлючи(ТекущееЗначение, ЗначениеИзПроверки);
		КонецЕсли;
		
	КонецЦикла;
	
	Для Каждого УдаляемыйКлюч Из МассивУдаляемых Цикл
		Коллекция.Удалить(УдаляемыйКлюч);
	КонецЦикла;
	
КонецПроцедуры


&НаКлиентеНаСервереБезКонтекста
Процедура ЗаполнитьСтруктуруСоответствиеРекурсивно(Приемник, Источник)
	
	ДобавлятьНовыеСвойства = НЕ СтрНачинаетсяС(ТипЗнч(Приемник), "Фикс");
	
	Для Каждого КлючИЗначение Из Источник Цикл
		
		Если (ТипЗнч(Приемник) = Тип("Структура") И НЕ Приемник.Свойство(КлючИЗначение.Ключ)) Тогда
			Если ДобавлятьНовыеСвойства Тогда
				Приемник.Вставить(КлючИЗначение.Ключ);
			Иначе
				Продолжить;
			КонецЕсли;
		КонецЕсли;
		
		ТипЗначения = ТипЗнч(КлючИЗначение.Значение);
		Если ТипЗначения = Тип("Структура")
			ИЛИ ТипЗначения = Тип("Соответствие") Тогда
			
			Если ТипЗнч(Приемник[КлючИЗначение.Ключ]) <> ТипЗначения Тогда
				Приемник[КлючИЗначение.Ключ]	= Новый(ТипЗначения);
			КонецЕсли;
			
			ЗаполнитьСтруктуруСоответствиеРекурсивно(Приемник[КлючИЗначение.Ключ], КлючИЗначение.Значение);
			
		Иначе
			
			Приемник[КлючИЗначение.Ключ] = КлючИЗначение.Значение;
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры


&НаКлиенте
Процедура ПрименитьИзменениеРеквизитаВРедакторе(СтруктураЗначений, ДополнительныеПараметры) Экспорт
	
	ЗначениеРеквизита = Неопределено;
	Если НЕ ТипЗнч(СтруктураЗначений) = Тип("Структура") 
		ИЛИ НЕ СтруктураЗначений.Свойство("ЗначениеРеквизита", ЗначениеРеквизита) Тогда
		Возврат;
	КонецЕсли;
	
	ИзменитьЗначениеРеквизитаОткрытойФормы(,,ЗначениеРеквизита);
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьФормуНастроекДинамическогоСписка(ЗначениеРеквизита = Неопределено)
	
	Если ЗначениеРеквизита = Неопределено Тогда
		ЗначениеРеквизита = ЗначениеРеквизитаОткрытойФормы();
	КонецЕсли;
	
	ПараметрыФормыНастроек = Новый Структура;
    ПараметрыФормыНастроек.Вставить("Заголовок" , "Настройка списка");
    ПараметрыФормыНастроек.Вставить("ИсточникДоступныхНастроек" , ЗначениеРеквизита.КомпоновщикНастроек.ПолучитьИсточникДоступныхНастроек());
    ПараметрыФормыНастроек.Вставить("Настройки" , ЗначениеРеквизита.КомпоновщикНастроек.Настройки);
    ПараметрыФормыНастроек.Вставить("ПользовательскиеНастройки" , ЗначениеРеквизита.КомпоновщикНастроек.ПользовательскиеНастройки);
    ПараметрыФормыНастроек.Вставить("ФиксированныеНастройки" , ЗначениеРеквизита.КомпоновщикНастроек.ФиксированныеНастройки);
	
	
	ОписаниеЗавершения = Новый ОписаниеОповещения("ПрименитьИзменениеРеквизитаВРедакторе", ЭтотОбъект);
	
	ОткрытьФорму(ПолныйПутьКФормеОбработки("ФормаНастроекДинамическогоСписка"),
	ПараметрыФормыНастроек, ЭтотОбъект, Истина,,,ОписаниеЗавершения,РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьФормуНастроекКомпоновки()
	
	ОписаниеРеквизита = Элементы.ОткрытыеФормыРеквизиты.ТекущиеДанные;
	Если ОписаниеРеквизита = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Попытка
		ЗначениеРеквизита = ЗначениеРеквизитаОткрытойФормы();
	Исключение
	    Возврат;
	КонецПопытки;
	
	Попытка
		ОписаниеРодителя = ОписаниеРеквизита.ПолучитьРодителя();
		ЗначениеРодителя = ЗначениеРеквизитаОткрытойФормы(,ОписаниеРодителя);
	Исключение
		ОписаниеРодителя = Неопределено;
	    ЗначениеРодителя = Неопределено;
	КонецПопытки;
	
	ИмяФормыНастроек = "ФормаНастроекКомпоновки";
		
	ПараметрыФормыНастроек = Новый Структура;
	Если ЭтоОтчетВРеквизитОтчетДляПроверкиТипа(ЗначениеРодителя) Тогда
		
		//ИмяФормыНастроек = "ФормаКомпоновщикаОтчета";
		ПараметрыФормыНастроек.Вставить("Отчет",  ЗначениеРодителя);
		
	Иначе
		
		ПараметрыФормыНастроек.Вставить("КомпоновщикНастроек", ЗначениеРеквизита);
		
	КонецЕсли;

	ОписаниеЗавершения = Новый ОписаниеОповещения("ПрименитьИзменениеРеквизитаВРедакторе", ЭтотОбъект);
	
	ОткрытьФорму(ПолныйПутьКФормеОбработки(ИмяФормыНастроек),
		ПараметрыФормыНастроек, ЭтотОбъект, Истина,,,
		ОписаниеЗавершения,РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	
КонецПроцедуры

&НаКлиенте
Функция ЭтоОтчетВРеквизитОтчетДляПроверкиТипа(ДанныеРеквизита)
	
	Попытка
		КопироватьДанныеФормы(ДанныеРеквизита, РеквизитОтчетДляПроверкиТипа);
		Возврат Истина;
	Исключение
	    Возврат Ложь;
	КонецПопытки;
	
КонецФункции


&НаКлиенте
Процедура ДополнитьИсториюПроверкиПроизвольногоРеквизитаТекущимЗначением()
	
	Если ПустаяСтрока(Реквизиты_ПроизвольныйРеквизит) 
		ИЛИ НЕ Реквизиты_ПроизвольныйРеквизит_История.НайтиПоЗначению(Реквизиты_ПроизвольныйРеквизит) = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	МаксимальноеЧислоЭлементовИстории = 10;
	
	Реквизиты_ПроизвольныйРеквизит_История.Вставить(0, Реквизиты_ПроизвольныйРеквизит, Реквизиты_ПроизвольныйРеквизит);
		
	Пока Истина Цикл
		КоличествоЭлементовИстории = Реквизиты_ПроизвольныйРеквизит_История.Количество();
		Если КоличествоЭлементовИстории <= МаксимальноеЧислоЭлементовИстории Тогда
			Прервать;
		Иначе
			Реквизиты_ПроизвольныйРеквизит_История.Удалить(КоличествоЭлементовИстории-1);
		КонецЕсли;
	КонецЦикла;
	
	Элементы.Реквизиты_ПроизвольныйРеквизит.СписокВыбора.Очистить();
	Для Каждого ТекущееЗначение Из Реквизиты_ПроизвольныйРеквизит_История Цикл
		Элементы.Реквизиты_ПроизвольныйРеквизит.СписокВыбора.Добавить(
		ТекущееЗначение.Значение, ТекущееЗначение.Представление, ТекущееЗначение.Пометка, ТекущееЗначение.Картинка);
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьНаличиеРеквивизита(ПутьКРеквизиту, ОписаниеФормы = Неопределено)
	
	Если ОписаниеФормы = Неопределено Тогда
		ОписаниеФормы = Элементы.ОткрытыеФормы.ТекущиеДанные;
	КонецЕсли;
	ТекущаяОткрытаяФорма = ТекущаяОткрытаяФорма(ОписаниеФормы);
	Если ОписаниеФормы = Неопределено ИЛИ ТекущаяОткрытаяФорма = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	
	
	
	СоставПути = СтрРазделить(ПутьКРеквизиту, ".");
	ТекущийРодитель = Неопределено;
	ТекущееЗначение = ТекущаяОткрытаяФорма;
	Для Каждого ТекущееСвойство Из СоставПути Цикл
		Если СвойствоОбъекта(ТекущееЗначение, ТекущееСвойство, ТекущееЗначение) Тогда
			ТекущийРодитель = ДобавитьОписаниеРеквизитаСПодчиненными(ТекущаяОткрытаяФорма, ОписаниеФормы, 
			ТекущееСвойство, ТекущееЗначение, ТекущийРодитель);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура СкопироватьЭлементыНастроек(ПриемникЗначения, ИсточникЗначения, ОчищатьПриемник = Истина)
    
    Если ТипЗнч(ИсточникЗначения) = Тип("УсловноеОформлениеКомпоновкиДанных")
        ИЛИ ТипЗнч(ИсточникЗначения) = Тип("ВариантыПользовательскогоПоляВыборКомпоновкиДанных")
        ИЛИ ТипЗнч(ИсточникЗначения) = Тип("ОформляемыеПоляКомпоновкиДанных")
        ИЛИ ТипЗнч(ИсточникЗначения) = Тип("ЗначенияПараметровДанныхКомпоновкиДанных") Тогда
        СоздаватьПоТипу = Ложь;
    Иначе
        СоздаватьПоТипу = Истина;
    КонецЕсли;
    
    ПриемникЭлементов = ПриемникЗначения.Элементы;
    Если ОчищатьПриемник Тогда
        ПриемникЭлементов.Очистить();
    КонецЕсли;
    ИсточникЭлементов = ИсточникЗначения.Элементы;
    
    Для каждого ЭлементИсточник Из ИсточникЭлементов Цикл
        
        Если ТипЗнч(ЭлементИсточник) = Тип("ЭлементПорядкаКомпоновкиДанных") Тогда
            //@skip-check bsl-legacy-check-expression-type
            Индекс = ИсточникЭлементов.Индекс(ЭлементИсточник);                            // Элементы порядка добавляем в начало

            ЭлементПриемник = ПриемникЭлементов.Вставить(Индекс, ТипЗнч(ЭлементИсточник));
        Иначе
            Если СоздаватьПоТипу Тогда
                ЭлементПриемник = ПриемникЭлементов.Добавить(ТипЗнч(ЭлементИсточник));
            Иначе
                ЭлементПриемник = ПриемникЭлементов.Добавить();
            КонецЕсли;
        КонецЕсли;
        
        ЗаполнитьЗначенияСвойств(ЭлементПриемник, ЭлементИсточник);
        
        // В некоторых коллекциях необходимо заполнить другие коллекции

        Если ТипЗнч(ИсточникЭлементов) = Тип("КоллекцияЭлементовУсловногоОформленияКомпоновкиДанных") Тогда
            СкопироватьЭлементыНастроек(ЭлементПриемник.Поля, ЭлементИсточник.Поля);
            СкопироватьЭлементыНастроек(ЭлементПриемник.Отбор, ЭлементИсточник.Отбор);
            ЗаполнитьЭлементыНастроек(ЭлементПриемник.Оформление, ЭлементИсточник.Оформление); 
        ИначеЕсли ТипЗнч(ИсточникЭлементов) = Тип("КоллекцияВариантовПользовательскогоПоляВыборКомпоновкиДанных") Тогда
            СкопироватьЭлементыНастроек(ЭлементПриемник.Отбор, ЭлементИсточник.Отбор);
        КонецЕсли;
        
        // В некоторых элементах коллекции необходимо заполнить другие коллекции

        Если ТипЗнч(ЭлементИсточник) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
            СкопироватьЭлементыНастроек(ЭлементПриемник, ЭлементИсточник);
        ИначеЕсли ТипЗнч(ЭлементИсточник) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда
            СкопироватьЭлементыНастроек(ЭлементПриемник, ЭлементИсточник);
        ИначеЕсли ТипЗнч(ЭлементИсточник) = Тип("ПользовательскоеПолеВыборКомпоновкиДанных") Тогда
            СкопироватьЭлементыНастроек(ЭлементПриемник.Варианты, ЭлементИсточник.Варианты);
        ИначеЕсли ТипЗнч(ЭлементИсточник) = Тип("ПользовательскоеПолеВыражениеКомпоновкиДанных") Тогда
            ЭлементПриемник.УстановитьВыражениеДетальныхЗаписей (ЭлементИсточник.ПолучитьВыражениеДетальныхЗаписей());
            ЭлементПриемник.УстановитьВыражениеИтоговыхЗаписей(ЭлементИсточник.ПолучитьВыражениеИтоговыхЗаписей());
            ЭлементПриемник.УстановитьПредставлениеВыраженияДетальныхЗаписей(ЭлементИсточник.ПолучитьПредставлениеВыраженияДетальныхЗаписей ());
            ЭлементПриемник.УстановитьПредставлениеВыраженияИтоговыхЗаписей(ЭлементИсточник.ПолучитьПредставлениеВыраженияИтоговыхЗаписей ());
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура ЗаполнитьЭлементыНастроек(ПриемникЗначения, ИсточникЗначения, ПервыйУровень = Неопределено)
    
    Если ТипЗнч(ПриемникЗначения) = Тип("КоллекцияЗначенийПараметровКомпоновкиДанных") Тогда
        КоллекцияЗначений = ИсточникЗначения;
    Иначе
        КоллекцияЗначений = ИсточникЗначения.Элементы;
    КонецЕсли;
    
    Для каждого ЭлементИсточник Из КоллекцияЗначений Цикл
        Если ПервыйУровень = Неопределено Тогда
            ЭлементПриемник = ПриемникЗначения.НайтиЗначениеПараметра(ЭлементИсточник.Параметр);
        Иначе
            ЭлементПриемник = ПервыйУровень.НайтиЗначениеПараметра(ЭлементИсточник.Параметр);
        КонецЕсли;
        Если ЭлементПриемник = Неопределено Тогда
            Продолжить;
        КонецЕсли;
        ЗаполнитьЗначенияСвойств(ЭлементПриемник, ЭлементИсточник);
        Если ТипЗнч(ЭлементИсточник) = Тип("ЗначениеПараметраКомпоновкиДанных") Тогда
            Если ЭлементИсточник.ЗначенияВложенныхПараметров.Количество() <> 0 Тогда
                ЗаполнитьЭлементыНастроек(ЭлементПриемник.ЗначенияВложенныхПараметров, 
                	ЭлементИсточник.ЗначенияВложенныхПараметров, ПриемникЗначения);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьРеквизитыФормыРазборомДанныхФормы(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, ВозможныеРодители)
	
	ДанныеФормы = Новый Массив;
	Для Каждого ТекущиеДанные Из ВозможныеРодители Цикл
		ДанныеФормы.Добавить(ЗначениеРеквизитаОткрытойФормы(СтрокаОткрытойФормы, ТекущиеДанные));
	КонецЦикла;
	
	РеквизитыФормыИзДанныхФормы = РеквизитыФормыИзДанныхФормы(ДанныеФормы);
	
	КэшРеквизитов = СтрокаОткрытойФормы.ТехническиеДанные.Реквизиты;
	
	ТекущийЗаход = 1;
	Пока ТекущийЗаход < 3 Цикл
		
		Для Каждого КлючИЗначение Из РеквизитыФормыИзДанныхФормы Цикл
			
			ПутьРеквизитаФормы = КлючИЗначение.Ключ;
			ИмяТекущегоПоля      = КлючИЗначение.Значение.Имя;
			РодительТекущегоПоля = КлючИЗначение.Значение.Родитель;
			
			Если ТекущийЗаход = 1 И НЕ ПустаяСтрока(РодительТекущегоПоля) Тогда
				Продолжить;
			ИначеЕсли ТекущийЗаход = 2 И ПустаяСтрока(РодительТекущегоПоля) Тогда
				Продолжить;
			КонецЕсли;
			
			Если НЕ КэшРеквизитов.Получить(ПутьРеквизитаФормы) = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			
			ИмяТекущегоПоля      = КлючИЗначение.Значение.Имя;
			РодительТекущегоПоля = КлючИЗначение.Значение.Родитель;
			РодительТекущегоПоля = КэшРеквизитов.Получить(РодительТекущегоПоля);
			
			ЗначениеТекущегоПоля = Неопределено;
			
			Если РодительТекущегоПоля = Неопределено Тогда
				Если СвойствоОбъекта(ТекущаяОткрытаяФорма, ИмяТекущегоПоля, ЗначениеТекущегоПоля) Тогда
					ДобавитьОписаниеРеквизитаСПодчиненными(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, ИмяТекущегоПоля, ЗначениеТекущегоПоля);
				КонецЕсли;
			Иначе
				РодительТекущегоПоля = СтрокаОткрытойФормы.Реквизиты.НайтиПоИдентификатору(РодительТекущегоПоля);
				ЗначениеРодителя = ЗначениеРеквизитаОткрытойФормы(СтрокаОткрытойФормы, РодительТекущегоПоля, ТекущаяОткрытаяФорма);
				Если СвойствоОбъекта(ЗначениеРодителя, ИмяТекущегоПоля, ЗначениеТекущегоПоля) Тогда
					ДобавитьОписаниеРеквизитаСПодчиненными(ТекущаяОткрытаяФорма, СтрокаОткрытойФормы, ИмяТекущегоПоля, ЗначениеТекущегоПоля, РодительТекущегоПоля);
				КонецЕсли;
			КонецЕсли;
			
		КонецЦикла;
		
		ТекущийЗаход = ТекущийЗаход + 1;
		
	КонецЦикла;
	
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция РеквизитыФормыИзДанныхФормы(ДанныеФормы)
	
	#Если ВебКлиент Тогда
        
        Возврат РеквизитыФормыИзДанныхФормыДляВебКлиента(ДанныеФормы);
        
    #Иначе
		
		РеквизитыФормы = Новый Соответствие;
		
		Для Каждого ТекущиеДанныеФормы Из ДанныеФормы Цикл
			
			СтрокаXML   = ЗначениеВСтрокуXML(ТекущиеДанныеФормы);
			ЧтениеXML   = Новый ЧтениеXML;
			ЧтениеXML.УстановитьСтроку(СтрокаXML);
			
			ТекущийРодитель = Неопределено;
			
			Пока ЧтениеXML.Прочитать() Цикл
				
				Если ЧтениеXML.Имя = "descriptions" 
					И ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
					
					Прервать;
					
				ИначеЕсли ЧтениеXML.Имя = "structure" 
					И ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
					
					ТекущийРодитель = Неопределено;
					АтрибутРодителя = ЧтениеXML.ПолучитьАтрибут("name");
					
					Если НЕ ТипЗнч(АтрибутРодителя) = Тип("Строка") Тогда
						Продолжить;
					КонецЕсли;
					
					ПутьРодителя = СтрРазделить(АтрибутРодителя, ".");
					КолвоПутиРодителя = ПутьРодителя.Количество();
					
					Если КолвоПутиРодителя = 1 Тогда
						ТекущийРодитель = ""; //Корень
					ИначеЕсли КолвоПутиРодителя = 2 Тогда
						ТекущийРодитель = ПутьРодителя.Получить(1);
					КонецЕсли;
					
					
				ИначеЕсли ТекущийРодитель <> Неопределено
					И ЧтениеXML.Имя = "field" 
					И ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
					
					ТекущееПоле = ЧтениеXML.ПолучитьАтрибут("name");
					ПолныйПуть  = ?(ПустаяСтрока(ТекущийРодитель), ТекущееПоле, ТекущийРодитель + "." + ТекущееПоле);
					
					Если РеквизитыФормы.Получить(ПолныйПуть) = Неопределено Тогда
						РеквизитыФормы.Вставить(ПолныйПуть, Новый Структура("Имя,Родитель", ТекущееПоле, ТекущийРодитель));
					КонецЕсли;
					
				КонецЕсли;
				
			КонецЦикла;
			
			ЧтениеXML.Закрыть();
			
		КонецЦикла;
		
    	
    	
    	Возврат РеквизитыФормы;
    
    #КонецЕсли
	
КонецФункции

&НаСервереБезКонтекста
Функция РеквизитыФормыИзДанныхФормыДляВебКлиента(Знач ДанныеФормы)
	
	Возврат РеквизитыФормыИзДанныхФормыДляВебКлиента(ДанныеФормы);
	
КонецФункции

#КонецОбласти

#Область КонсольКода

&НаКлиентеНаСервереБезКонтекста
Процедура ВыполнитьКодНаКлиенте(ТекущаяФорма, ТекстНаКлиенте, ТекстНаСервере, ДополнительныеПараметры)
	
	#Если ВебКлиент Тогда
		ВызватьИсключение "Выполнение кода недоступно в веб-клиенте!";
	#Иначе
		//@skip-check server-execution-safe-mode - инструмент для разработчика
		Выполнить(ТекстНаКлиенте);
	#КонецЕсли
	
КонецПроцедуры

// Выполнить код на сервере.
// @skip-check export-method-in-command-form-module - используется в панели кода
// 
// Параметры:
//  ТекстНаСервере - Строка
//  ДополнительныеПараметры - Структура
&НаСервереБезКонтекста
Процедура ВыполнитьКодНаСервере(ТекстНаСервере, ДополнительныеПараметры = Неопределено) Экспорт
	
	//@skip-check server-execution-safe-mode - инструмент для разработчика
	Выполнить(ТекстНаСервере);

КонецПроцедуры

#КонецОбласти

#Область НастройкиФормИзХранилища

&НаКлиентеНаСервереБезКонтекста
Процедура ОбновитьСохраненныеНастройкиФормИзХранилища(Форма, СтрокаОткрытойФормы = Неопределено)
	
	Если НЕ ЗначениеНастройки(Форма, "РаботаСНастройкамиФорм") Тогда
		Возврат;
	КонецЕсли;
	
	#Если Клиент Тогда
		Состояние("Обновление информации о настройках форм");
	#КонецЕсли
	
	КоллекцияСтрокОткрытыхФорм = Новый Массив;
	ИменаПроверяемыхФорм = Новый Массив;
	
	Если СтрокаОткрытойФормы = Неопределено Тогда
		КоллекцияСтрокОткрытыхФорм = Форма.ОткрытыеФормы;
	ИначеЕсли ТипЗнч(СтрокаОткрытойФормы) = Тип("Число") Тогда
		КоллекцияСтрокОткрытыхФорм.Добавить(Форма.ОткрытыеФормы.НайтиПоИдентификатору(СтрокаОткрытойФормы));
	Иначе
		КоллекцияСтрокОткрытыхФорм.Добавить(СтрокаОткрытойФормы);
	КонецЕсли;
	
	Для Каждого ТекущаяОткрытаяФорма Из КоллекцияСтрокОткрытыхФорм Цикл
		ТекущаяОткрытаяФорма.НастройкиИзХранилища.Очистить();
		ИменаПроверяемыхФорм.Добавить(ТекущаяОткрытаяФорма.ИмяФормы);
	КонецЦикла;
	
	Если ИменаПроверяемыхФорм.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	СохраненныеНастройкиФорм = СохраненныеНастройкиФормИзХранилища(ИменаПроверяемыхФорм);
	
	#Если Клиент Тогда
		НомерТекущейФормы = 0;
		ВсегоНайденноФорм = КоллекцияСтрокОткрытыхФорм.Количество();
	#КонецЕсли
	
	Для Каждого ТекущаяОткрытаяФорма Из КоллекцияСтрокОткрытыхФорм Цикл
		
		#Если Клиент Тогда
			Состояние("Обновление информации о настройках формы " + ТекущаяОткрытаяФорма.ИмяФормы, Цел(НомерТекущейФормы/ВсегоНайденноФорм*100));
		#КонецЕсли
	
		СохраненныеНастройкиФормы = СохраненныеНастройкиФорм.Получить(ТекущаяОткрытаяФорма.ИмяФормы);
		Если СохраненныеНастройкиФормы = Неопределено Тогда
			Возврат;
		КонецЕсли;
		
		Для Каждого СохраненнаяНастройка Из СохраненныеНастройкиФормы Цикл
			ЗаполнитьЗначенияСвойств(ТекущаяОткрытаяФорма.НастройкиИзХранилища.Добавить(), СохраненнаяНастройка);
		КонецЦикла;
		
	КонецЦикла;
	
	#Если Клиент Тогда
		Состояние("Обновление информации о настройках форм");
	#КонецЕсли
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция СохраненныеНастройкиФормИзХранилища(ИменаФорм)
	
	СохраненныеНастройкиФорм = Новый Соответствие;
	
	Выборка = ХранилищеСистемныхНастроек.Выбрать(
		Новый Структура("Пользователь", ПользователиИнформационнойБазы.ТекущийПользователь().Имя));
		
	Пока Истина Цикл
		
		Попытка
			Если НЕ Выборка.Следующий() Тогда	//Иногда выпадают ошибки. Так их можно игнорировать
				Прервать;
			КонецЕсли;
		Исключение
			Продолжить;
		КонецПопытки;
		
		Для Каждого ИмяФормы Из ИменаФорм Цикл
			
			Если НЕ СтрНайти(Выборка.КлючОбъекта, ИмяФормы) = 1 Тогда
				Продолжить;
			КонецЕсли;
			
			ОписаниеНастроек = СохраненныеНастройкиФорм.Получить(ИмяФормы);
			Если ОписаниеНастроек = Неопределено Тогда
				ОписаниеНастроек = Новый Массив;
			КонецЕсли;
			
			КлючиСвойств = "КлючОбъекта,КлючОбъектаКраткий,КлючНастроек,НастройкиСтрокойВнутр";
			ОписаниеНастройки = Новый Структура(КлючиСвойств);
			ЗаполнитьЗначенияСвойств(ОписаниеНастройки, Выборка);
			ОписаниеНастройки.КлючОбъектаКраткий    = Сред(Выборка.КлючОбъекта, СтрДлина(ИмяФормы)+1);
			ОписаниеНастройки.НастройкиСтрокойВнутр = ЗначениеВСтрокуВнутр(Выборка.Настройки);
			ОписаниеНастроек.Добавить(ОписаниеНастройки);
			
			СохраненныеНастройкиФорм.Вставить(ИмяФормы, ОписаниеНастроек);
			
		КонецЦикла;
		
	КонецЦикла;	
	
	Возврат СохраненныеНастройкиФорм;
	
КонецФункции

&НаСервереБезКонтекста
Процедура УдалитьНастройкуФормыИзХранилища(КлючОбъекта, КлючНастроек)
	
	Если НЕ ПустаяСтрока(КлючОбъекта) Тогда
		ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, 
			КлючНастроек, ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура СохранитьНастройкуФормыВХранилище(КлючОбъекта, КлючНастроек, НастройкиСтрокойВнутр)
	
	Если НЕ ПустаяСтрока(КлючОбъекта) Тогда		
		Попытка
			Настройки = ?(ПустаяСтрока(НастройкиСтрокойВнутр), Неопределено, ЗначениеИзСтрокиВнутр(НастройкиСтрокойВнутр));
		Исключение
			ВызватьИсключение "Не удалось обернуть строку внутр в значение!";
		КонецПопытки;
		ХранилищеСистемныхНастроек.Сохранить(КлючОбъекта, КлючНастроек, Настройки, , ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
		НастройкиСтрокойВнутр = ЗначениеВСтрокуВнутр(Настройки);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ИсторияОткрытияФорм

&НаКлиентеНаСервереБезКонтекста
Процедура ОбновитьИсториюОткрытияФорм(Форма, КоллекцияФорм = Неопределено)
	
	Если КоллекцияФорм = Неопределено Тогда
		КоллекцияФорм = Форма.ОткрытыеФормы;
	КонецЕсли;
	
	//Подготавливаем соответствие, которое на каждую навигационную ссылку хранит строки описания открытых форм
	ОписанияФормПоСсылкам = Новый Соответствие;
	Для Каждого ОписаниеФормы Из КоллекцияФорм Цикл
		
		Если ПустаяСтрока(ОписаниеФормы.НавигационнаяСсылка) Тогда
			Продолжить;
		КонецЕсли;
		
		ОписаниеФормы.ИсторияРаботы.Очистить();
		
		ФормыНавигационнойСсылки = ОписанияФормПоСсылкам.Получить(ОписаниеФормы.НавигационнаяСсылка);
		Если ФормыНавигационнойСсылки = Неопределено Тогда
			ФормыНавигационнойСсылки = Новый Массив;
		КонецЕсли;
		
		ФормыНавигационнойСсылки.Добавить(ОписаниеФормы);
		
		ОписанияФормПоСсылкам.Вставить(ОписаниеФормы.НавигационнаяСсылка, ФормыНавигационнойСсылки);
		
	КонецЦикла;
	
	
	Если НЕ ЗначениеНастройки(Форма, "ПоказыватьИсториюОткрытияФормы") Тогда
		Возврат;
	КонецЕсли;
	
	#Если Клиент Тогда
		Состояние("Обновление информации о истории открытия форм");
	#КонецЕсли
	
		
	
	//Перебираем историю и заполняем данные
	ВсяИсторияРаботы = ИсторияРаботыПользователя.Получить();
	Для Каждого ТекущаяИсторияРаботы Из ВсяИсторияРаботы Цикл
		
		ФормыНавигационнойСсылки = ОписанияФормПоСсылкам.Получить(ТекущаяИсторияРаботы.НавигационнаяСсылка);
		Если ФормыНавигационнойСсылки = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Для Каждого ОписаниеФормы Из ФормыНавигационнойСсылки Цикл
			ЗаполнитьЗначенияСвойств(ОписаниеФормы.ИсторияРаботы.Добавить(), ТекущаяИсторияРаботы);
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура ОбновитьИсториюОткрытияФормы(Форма, ОписаниеФормы = Неопределено)
	
	Если НЕ ЗначениеНастройки(Форма, "ПоказыватьИсториюОткрытияФормы") Тогда
		Возврат;
	КонецЕсли;
	
	Если ОписаниеФормы = Неопределено Тогда
		ОписаниеФормы = Форма.Элементы.ОткрытыеФормы.ТекущиеДанные;
		Если ОписаниеФормы = Неопределено Тогда
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
	ОбновитьИсториюОткрытияФорм(Форма, ЗначениеВМассиве(ОписаниеФормы));
	
КонецПроцедуры

#КонецОбласти

#Область ОткрытиеНовойФормы

&НаКлиенте
Процедура ОткрытьНовуюФорму(ВыбранноеЗначение = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
	
	Если НЕ ТипЗнч(ВыбранноеЗначение) = Тип("Структура") Тогда
		Возврат;
	КонецЕсли;
	
	Попытка
		
		Если ПустаяСтрока(ВыбранноеЗначение.ПолноеИмя) Тогда
			ПерейтиПоНавигационнойСсылке(ВыбранноеЗначение.НавигационнаяСсылка);
		Иначе
			ОткрытьФорму(ВыбранноеЗначение.ПолноеИмя,ВыбранноеЗначение.Параметры,,,,,,РежимОткрытияОкнаФормы.Независимый);
		КонецЕсли;
		
		НачатьОбновлениеОткрытыхФорм();
		
		Активизировать();
		
		ВсеОкна = ПолучитьОкна();
		ПоследнееОкно = ВсеОкна.Получить(ВсеОкна.Количество()-1);
		ФормаОкна = ПоследнееОкно.Содержимое[0];
		ФормаОкна.РежимОткрытияОкна = РежимОткрытияОкнаФормы.Независимый;
			
	Исключение
		
		СообщитьПользователю(ОписаниеОшибки());
		
	КонецПопытки;
	
КонецПроцедуры

#КонецОбласти

#Область Прочее

&НаКлиенте
Функция ОткрытаяФормаПоУникальномуИдентификатору(УникальныйИдентификатор)
	
	ВсеОткрытыеОкна = ПолучитьОкна();
	
	КоличествоОкон = ВсеОткрытыеОкна.Количество();
	
	Для ИндексОкна = 0 По КоличествоОкон-1 Цикл
		
		ТекущееОкно = ВсеОткрытыеОкна[ИндексОкна];
		КоличествоСодержимого = ТекущееОкно.Содержимое.Количество();
		
		Для ИндексСодержимого = 0 По КоличествоСодержимого - 1 Цикл
			
			ТекущаяФорма = ТекущееОкно.Содержимое[ИндексСодержимого];
			Если ТипЗнч(ТекущаяФорма) <> Тип("ФормаКлиентскогоПриложения") Тогда
				Продолжить;
			КонецЕсли;
			
			Если ТекущаяФорма.УникальныйИдентификатор = НовыйУникальныйИдентификатор(УникальныйИдентификатор) Тогда
				Возврат ТекущаяФорма;
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;
	
	
КонецФункции

&НаСервереБезКонтекста
Процедура ОбновитьИзбранныеСсылки(ИзбранныеСсылки, Знач ИзбранноеРаботыПользователя = Неопределено)
	
	Если ИзбранноеРаботыПользователя = Неопределено Тогда
		ИзбранноеРаботыПользователя = ХранилищеСистемныхНастроек.Загрузить("Общее/ИзбранноеРаботыПользователя");
	КонецЕсли;
	
	ИзбранныеСсылки = НавигационныеСсылкиИзбранного(ИзбранноеРаботыПользователя);
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция НавигационныеСсылкиИзбранного(ИзбранноеРаботыПользователя)
	
	НавигационныеСсылки = Новый Массив;
	
	Если ТипЗнч(ИзбранноеРаботыПользователя) = Тип("ИзбранноеРаботыПользователя") Тогда
		Для Каждого ЭлементИзбранного Из ИзбранноеРаботыПользователя Цикл
			НавигационныеСсылки.Добавить(ЭлементИзбранного.НавигационнаяСсылка);
		КонецЦикла;
	КонецЕсли;
	
	Возврат НавигационныеСсылки;
	
КонецФункции

&НаКлиенте
Процедура Вопрос_УдалитьНастройкуФормыИзХранилища(
	РезультатВопроса = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт
	
	Если РезультатВопроса = Неопределено Тогда
		
		ПоказатьВопрос(
		Новый ОписаниеОповещения("Вопрос_УдалитьНастройкуФормыИзХранилища", ЭтотОбъект, ДополнительныеПараметры),
		"Удалить настройку из хранилища?", РежимДиалогаВопрос.ДаНет);
		
	ИначеЕсли РезультатВопроса = КодВозвратаДиалога.Да Тогда
		
		СтрокаФормы = ОткрытыеФормы.НайтиПоИдентификатору(ДополнительныеПараметры.СтрокаФормы);
		Если СтрокаФормы = Неопределено Тогда
			Возврат;
		КонецЕсли;
		
		СтрокаНастройки = СтрокаФормы.НастройкиИзХранилища.НайтиПоИдентификатору(ДополнительныеПараметры.СтрокаНастройки);
		Если СтрокаНастройки = Неопределено Тогда
			Возврат;
		КонецЕсли;
		
		УдалитьНастройкуФормыИзХранилища(СтрокаНастройки.КлючОбъекта, СтрокаНастройки.КлючНастроек);
		СтрокаФормы.НастройкиИзХранилища.Удалить(СтрокаНастройки);
		
	КонецЕсли;	
	
КонецПроцедуры

&НаКлиенте
Функция ПолныйПутьКФормеОбработки(ИмяФормыОбработки) Экспорт
	
	Возврат СтрШаблон("%1.Форма.%2", ВспомогательныеЗначения.Метаданные.ПолноеИмя, ИмяФормыОбработки);
	
КонецФункции

&НаКлиенте
Процедура ПрименитьНастройкиОбработки(НовыеНастройки = Неопределено)
	
	ТребуетсяОбновитьНастройкиИзХранилища	= Ложь;
	ТребуетсяОбновитьОткрытыеФормы			= Ложь;
	ТребуетсяОбновитьОткрытыеФормы			= Ложь;
	ТребуетсяОтсортироватьФормы				= Ложь;
	ТребуетсяОбновитьИсториюОткрытияФорм	= Ложь;
	ТребуетсяОбновитьСвойстваФормы			= Ложь;
	
	Если ТипЗнч(НовыеНастройки) = Тип("Структура") Тогда
        
        ДополнитьНовыеНастройкиТекущими(НовыеНастройки);
        
		Если ЗначениеНастройки(ЭтотОбъект, "РаботаСНастройкамиФорм",,НовыеНастройки) = Истина 
			И ЗначениеНастройки(ЭтотОбъект, "РаботаСНастройкамиФорм") = Ложь Тогда
			ТребуетсяОбновитьНастройкиИзХранилища	= Истина;
		КонецЕсли;
		
		Если ИзменилисьНастройкиОбработки(НовыеНастройки, "РаботаСЭлементамиФорм") Тогда
			ТребуетсяОбновитьОткрытыеФормы	= Истина;
		ИначеЕсли ИзменилисьНастройкиОбработки(НовыеНастройки, "ПоказыватьМенеджерОкон") Тогда
			ТребуетсяОбновитьОткрытыеФормы	= Истина;
		ИначеЕсли ЗначениеНастройки(ЭтотОбъект, "РаботаСРеквизитамиФорм",,НовыеНастройки)
			И ( ИзменилисьНастройкиОбработки(НовыеНастройки, "РаботаСРеквизитамиФорм") 
			ИЛИ ИзменилисьНастройкиОбработки(НовыеНастройки, "АвтоматическиПроверяемыеРеквизиты") ) Тогда
			ТребуетсяОбновитьОткрытыеФормы	= Истина;
		ИначеЕсли ИзменилисьНастройкиОбработки(НовыеНастройки, "СортироватьПоЗаголовкуФормы") Тогда
			Если ЗначениеНастройки(ЭтотОбъект, "СортироватьПоЗаголовкуФормы") = Истина Тогда
				ТребуетсяОбновитьОткрытыеФормы	= Истина;
			Иначе
				ТребуетсяОтсортироватьФормы		= Истина;
			КонецЕсли;
		КонецЕсли;
		
		Если НЕ ТребуетсяОбновитьОткрытыеФормы Тогда
			Если ЗначениеНастройки(ЭтотОбъект, "ПоказыватьИсториюОткрытияФормы") = Ложь
				И ИзменилисьНастройкиОбработки(НовыеНастройки, "ПоказыватьИсториюОткрытияФормы") Тогда
				ТребуетсяОбновитьИсториюОткрытияФорм	= Истина;
			КонецЕсли;
			Если ЗначениеНастройки(ЭтотОбъект, "РаботаСоСвойствамиФорм") = Ложь
				И ИзменилисьНастройкиОбработки(НовыеНастройки, "РаботаСоСвойствамиФорм") Тогда
				ТребуетсяОбновитьСвойстваФормы	= Истина;
			КонецЕсли;
		КонецЕсли;
		
		ЗаполнитьЗначенияСвойств(ЭтотОбъект, НовыеНастройки);
		
	КонецЕсли;

	
	УстановитьСвойствоЭлемента(ЭтотОбъект, "ОсновнаяГруппаПраво_Элементы", "Видимость", 
		ЗначениеНастройки(ЭтотОбъект, "РаботаСЭлементамиФорм"));
	УстановитьСвойствоЭлемента(ЭтотОбъект, "ОсновнаяГруппаПраво_Свойства", "Видимость", 
		ЗначениеНастройки(ЭтотОбъект, "РаботаСоСвойствамиФорм"));
	УстановитьСвойствоЭлемента(ЭтотОбъект, "ОсновнаяГруппаПраво_Реквизиты", 
		"Видимость", ЗначениеНастройки(ЭтотОбъект, "РаботаСРеквизитамиФорм"));
	УстановитьСвойствоЭлемента(ЭтотОбъект, "ОсновнаяГруппаПраво_НастройкиИзХранилища", 
		"Видимость", ЗначениеНастройки(ЭтотОбъект, "РаботаСНастройкамиФорм"));
	УстановитьСвойствоЭлемента(ЭтотОбъект, "ОсновнаяГруппаПраво_КонсольКода",
		"Видимость", ЗначениеНастройки(ЭтотОбъект, "РаботаСКонсольюКода"));
	УстановитьСвойствоЭлемента(ЭтотОбъект, "ОсновнаяГруппаПраво_История", 
		"Видимость", ЗначениеНастройки(ЭтотОбъект, "ПоказыватьИсториюОткрытияФормы"));
	УстановитьСвойствоЭлемента(ЭтотОбъект, "ОсновнаяГруппаПраво_Параметры", 
		"Видимость", ЗначениеНастройки(ЭтотОбъект, "РаботаСПараметрамиФорм"));
	
	НеобходимоеОтображениеПодсказки	= ОтображениеПодсказки[
		?(ЗначениеНастройки(ЭтотОбъект, "СкрыватьКнопкиПодсказок"), "Всплывающая", "Кнопка")];
	Для Каждого ИмяЭлементаФормы Из ВспомогательныеЗначения.ЭлементыСКнопкамиПодсказки Цикл
		УстановитьСвойствоЭлемента(ЭтотОбъект, ИмяЭлементаФормы, "ОтображениеПодсказки", НеобходимоеОтображениеПодсказки);
	КонецЦикла;
	
	Если ТребуетсяОбновитьОткрытыеФормы Тогда
		ОбновитьОткрытыеФормы();
	Иначе
		Если ТребуетсяОтсортироватьФормы Тогда
			ОтсортироватьОткрытыеФормы(ЭтотОбъект);
		КонецЕсли;
		Если ТребуетсяОбновитьСвойстваФормы Тогда
			ОбновитьСвойстваОткрытыхФорм();
		КонецЕсли;
		Если ТребуетсяОбновитьНастройкиИзХранилища Тогда
			ОбновитьСохраненныеНастройкиФормИзХранилища(ЭтотОбъект);
		КонецЕсли;
		Если ТребуетсяОбновитьИсториюОткрытияФорм Тогда
			ОбновитьИсториюОткрытияФорм(ЭтотОбъект);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ДополнитьНовыеНастройкиТекущими(НовыеНастройки)
    
    Для Каждого КлючНастройки Из ВспомогательныеЗначения.РеквизитыНастроекФормы Цикл
        
        Если НовыеНастройки.Свойство(КлючНастройки) Тогда
            Продолжить;
        КонецЕсли;
        
        НовыеНастройки.Вставить(КлючНастройки, ЗначениеНастройки(ЭтотОбъект,,КлючНастройки));
        
    КонецЦикла;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеНастройки(Форма, ИмяНастройки = Неопределено, КлючНастройки = Неопределено, КоллекцияНастроек = Неопределено)
    
    Если КоллекцияНастроек = Неопределено Тогда
        КоллекцияНастроек = Форма;
    КонецЕсли;
    
    Если ИмяНастройки = Неопределено Тогда
        ИмяНастройки = СтрЗаменить(КлючНастройки, Форма.ВспомогательныеЗначения.ПриставкаРеквизитовНастроек, "");
    ИначеЕсли КлючНастройки = Неопределено Тогда
        КлючНастройки= Форма.ВспомогательныеЗначения.ПриставкаРеквизитовНастроек + ИмяНастройки;
    КонецЕсли;
    
    ЗначениеНастройки   = КоллекцияНастроек[КлючНастройки];
    
    #Если ВебКлиент Тогда
        Если ИмяНастройки = "РаботаСПараметрамиФорм" Тогда
            ЗначениеНастройки   = Ложь;
        КонецЕсли;
    #КонецЕсли
    
    Возврат ЗначениеНастройки;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьЗначениеНастройки(Форма, ИмяНастройки, ЗначениеНастройки)
    
    Форма[Форма.ВспомогательныеЗначения.ПриставкаРеквизитовНастроек + ИмяНастройки]  = ЗначениеНастройки;
	
КонецПроцедуры

&НаКлиенте
Функция ИзменилисьНастройкиОбработки(НовыеНастройки, ИмяНастройки)
    
    Возврат НЕ ЗначенияРавны(
        ЗначениеНастройки(ЭтотОбъект, ИмяНастройки), 
        ЗначениеНастройки(ЭтотОбъект, ИмяНастройки,,НовыеНастройки)
        );
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ЗначенияРавны(Значение1, Значение2)
	
	Если ТипЗнч(Значение1) = Тип("СписокЗначений") И ТипЗнч(Значение2) = Тип("СписокЗначений") Тогда
		Возврат ЗначениеВСтрокуXML(Значение1) = ЗначениеВСтрокуXML(Значение2);
	Иначе
		Возврат Значение1 = Значение2;
	КонецЕсли;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьСвойствоЭлемента(Форма, ЭлементИлиИмя, Свойство, Значение)
	
	ЭлементФормы = ?(ТипЗнч(ЭлементИлиИмя) = Тип("Строка"),Форма.Элементы.Найти(ЭлементИлиИмя),ЭлементИлиИмя);
	
	Если ЭлементФормы <> Неопределено И ЭлементФормы[Свойство] <> Значение Тогда
		ЭлементФормы[Свойство] = Значение;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
// Проверяет строку на соответствие логике формирования ключей в 1С
//
// Параметры:
//  Строка  			- строка - строка, которую необходимо проверить
//  СообщатьОбОшибке  	- булево - выдавать ли информативное сообщение пользователю при ошибке
//
// Возвращаемое значение:
//   булево - соответствует ли строка формату
//
Функция СтрокаВерногоФормата(Строка)
		
	СтруктураДляПроверки = Новый Структура;
	
	Попытка
		
		СтруктураДляПроверки.Вставить(Строка);
		СтрокаВерногоФормата = Истина;
		
	Исключение
		
		СтрокаВерногоФормата = Ложь;
		
	КонецПопытки;
	
	Возврат СтрокаВерногоФормата;
	
КонецФункции


&НаКлиентеНаСервереБезКонтекста
// Формирует и выводит сообщение, которое может быть связано с элементом 
// управления формы.
// @skip-check method-too-many-params, use-non-recommended-method - это метод БСП
//
//  Параметры
//  ТекстСообщенияПользователю - Строка - текст сообщения.
//  КлючДанных                 - ЛюбаяСсылка - на объект информационной базы.
//                               Ссылка на объект информационной базы, к которому это сообщение относится,
//                               или ключ записи.
//  Поле                       - Строка - наименование реквизита формы.
//  ПутьКДанным                - Строка - путь к данным (путь к реквизиту формы).
//  Отказ                      - Булево - Выходной параметр.
//                               Всегда устанавливается в значение Истина.
//
//	Пример:
//
//	1. Для вывода сообщения у поля управляемой формы, связанного с реквизитом объекта:
//	ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
//		НСтр("ru = 'Сообщение об ошибке.'"), ,
//		"ПолеВРеквизитеФормыОбъект",
//		"Объект");
//
//	Альтернативный вариант использования в форме объекта:
//	ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
//		НСтр("ru = 'Сообщение об ошибке.'"), ,
//		"Объект.ПолеВРеквизитеФормыОбъект");
//
//	2. Для вывода сообщения рядом с полем управляемой формы, связанным с реквизитом формы:
//	ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
//		НСтр("ru = 'Сообщение об ошибке.'"), ,
//		"ИмяРеквизитаФормы");
//
//	3. Для вывода сообщения связанного с объектом информационной базы.
//	ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
//		НСтр("ru = 'Сообщение об ошибке.'"), ОбъектИнформационнойБазы, "Ответственный",,Отказ);
//
// 4. Для вывода сообщения по ссылке на объект информационной базы.
//	ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
//		НСтр("ru = 'Сообщение об ошибке.'"), Ссылка, , , Отказ);
//
// Случаи некорректного использования:
//  1. Передача одновременно параметров КлючДанных и ПутьКДанным.
//  2. Передача в параметре КлючДанных значения типа отличного от допустимых.
//  3. Установка ссылки без установки поля (и/или пути к данным).
//
Процедура СообщитьПользователю(
		Знач ТекстСообщенияПользователю,
		Знач КлючДанных = Неопределено,
		Знач Поле = "",
		Знач ПутьКДанным = "",
		Отказ = Ложь)
	
	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = ТекстСообщенияПользователю;
	Сообщение.Поле = Поле;
	
	ЭтоОбъект = Ложь;
	
#Если НЕ ТонкийКлиент И НЕ ВебКлиент Тогда
	Если КлючДанных <> Неопределено
	   И XMLТипЗнч(КлючДанных) <> Неопределено Тогда
		ТипЗначенияСтрокой = XMLТипЗнч(КлючДанных).ИмяТипа;
		ЭтоОбъект = Найти(ТипЗначенияСтрокой, "Object.") > 0;
	КонецЕсли;
#КонецЕсли
	
	Если ЭтоОбъект Тогда
		Сообщение.УстановитьДанные(КлючДанных);
	Иначе
		Сообщение.КлючДанных = КлючДанных;
	КонецЕсли;
	
	Если НЕ ПустаяСтрока(ПутьКДанным) Тогда
		Сообщение.ПутьКДанным = ПутьКДанным;
	КонецЕсли;
		
	Сообщение.Сообщить();
	
	Отказ = Истина;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыДерево(КоллекцияСортировки, КолонкаСортировки, ВключатьПодчиненные = Ложь)
	
	КоллекцияСтрок	= КоллекцияСортировки.ПолучитьЭлементы();
	
	СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки);
	
	Если ВключатьПодчиненные Тогда
		Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
			СортироватьДанныеФормыДерево(ТекущаяСтрока, КолонкаСортировки, ВключатьПодчиненные);
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки)
	
	ПараметрыЗначений		= Новый Соответствие;
	СортированныеЗначения	= Новый СписокЗначений;
	
	Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
		
		ТекущееЗначение	= ТекущаяСтрока[КолонкаСортировки];
		
		ПараметрыЗначения	= ПараметрыЗначений.Получить(ТекущееЗначение);
		Если ПараметрыЗначения = Неопределено Тогда
			ПараметрыЗначения	= Новый Массив;
			ПараметрыЗначений.Вставить(ТекущееЗначение, ПараметрыЗначения);
			СортированныеЗначения.Добавить(ТекущееЗначение);
		КонецЕсли;
		
		ПараметрыЗначения.Добавить(ТекущаяСтрока);
		
	КонецЦикла;
	
	СортированныеЗначения.СортироватьПоЗначению(НаправлениеСортировки.Возр);
	
	
	НовыйИндекс	= 0;
	Для Каждого ТекущееЗначение Из СортированныеЗначения Цикл
		
		МассивСтрок	= ПараметрыЗначений.Получить(ТекущееЗначение.Значение);
		Для Каждого ТекущаяСтрока Из МассивСтрок Цикл
			
			ТекущийИндекс	= КоллекцияСтрок.Индекс(ТекущаяСтрока);
			ШагСдвига		= НовыйИндекс - ТекущийИндекс;
			Если НЕ ШагСдвига = 0 Тогда
				КоллекцияСтрок.Сдвинуть(ТекущийИндекс, ШагСдвига);
			КонецЕсли;
			
			НовыйИндекс	= НовыйИндекс + 1;
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция ВложенноеСвойствоОбъектаВПопытке(Объект, ПутьКСвойству, ЗначениеСвойства = Неопределено)
	
	Попытка
		Возврат ВложенноеСвойствоОбъекта(Объект, ПутьКСвойству, ЗначениеСвойства);
	Исключение
		Возврат Ложь;
	КонецПопытки;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ВложенноеСвойствоОбъекта(Объект, ПутьКСвойству, ЗначениеСвойства = Неопределено)
	
	ТекущийОбъект		= Объект;
	
	ТипыБезСвойств		= ОписаниеТиповНеИмеющихСвойств();

	ВсеВложения			= СтрРазделить(ПутьКСвойству, ".", Истина);
	КоличествоВложений	= ВсеВложения.Количество();
		
	Для НомерТекущегоВложения = 1 По КоличествоВложений Цикл
		
		Если ТипыБезСвойств.СодержитТип(ТипЗнч(ТекущийОбъект)) Тогда
			Прервать;
		КонецЕсли;
		
		ТекущееВложение	= ВсеВложения.Получить(НомерТекущегоВложения - 1);
		
		ЕстьСвойство	= СвойствоОбъекта(ТекущийОбъект, ТекущееВложение, ТекущийОбъект);
		
		Если ЕстьСвойство Тогда
			Если НомерТекущегоВложения = КоличествоВложений Тогда
				ЗначениеСвойства	= ТекущийОбъект;
				Возврат Истина;
			КонецЕсли;
		Иначе
			ТекущийОбъект	= Неопределено;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Ложь;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция СвойствоОбъекта(Объект, Ключ, Значение = Неопределено)
	
	РезультатПроверки = Ложь;
	Если ТипЗнч(Объект) = Тип("Структура")
		ИЛИ ТипЗнч(Объект) = Тип("ДанныеФормыСтруктура")
		ИЛИ ТипЗнч(Объект) = Тип("ДанныеФормыСтруктураСКоллекцией") Тогда
		
		РезультатПроверки = Объект.Свойство(Ключ, Значение);
		
	ИначеЕсли ТипЗнч(Объект) = Тип("Соответствие") Тогда
		
		Значение = Объект.Получить(Ключ);
		РезультатПроверки = (НЕ Значение = Неопределено);
		
		
	Иначе
		
		#Если Сервер ИЛИ ТолстыйКлиентОбычноеПриложение ИЛИ ВнешнееСоединение Тогда
			
			МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(Объект));
			Если МетаданныеОбъекта <> Неопределено 
				И ЭтоОбъектСсылочногоТипа(МетаданныеОбъекта) Тогда
				
				КоллекцииСвойств = Новый Массив;
				КоллекцииСвойств.Добавить("Реквизиты");
				КоллекцииСвойств.Добавить("СтандартныеРеквизиты");
				КоллекцииСвойств.Добавить("ТабличныеЧасти");
				
			КонецЕсли;
			
		#КонецЕсли
		
		ВременныйИдентификатор	= Новый УникальныйИдентификатор();
		ВременнаяСтруктура		= Новый Структура(Ключ, ВременныйИдентификатор);
		ЗаполнитьЗначенияСвойств(ВременнаяСтруктура, Объект);
		
		Если ВременныйИдентификатор = ВременнаяСтруктура[Ключ] Тогда
			РезультатПроверки = Ложь;
		Иначе
			Значение	= ВременнаяСтруктура[Ключ];
			РезультатПроверки = Истина;
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат РезультатПроверки;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция ОписаниеТиповНеИмеющихСвойств()
	
	Возврат Новый ОписаниеТипов("Неопределено,Null,Строка,Число,Дата,Булево,УникальныйИдентификатор");
		
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция СтруктураИзОписанияЭлементаФормы(Форма, ОписаниеЭлементаФормы)
	
	СтруктураИзОписания	= Новый Структура;
	
	Для Каждого СвойствоЭлементов Из Форма.ВспомогательныеЗначения.СвойстваЭлементов Цикл
		СтруктураИзОписания.Вставить(СвойствоЭлементов);
	КонецЦикла;
	
	ЗаполнитьЗначенияСвойств(СтруктураИзОписания, ОписаниеЭлементаФормы);
	
	Возврат СтруктураИзОписания;
	
КонецФункции

// Создает массив и помещает в него переданное значение.
//
// Параметры:
//  Значение - Произвольный - любое значение.
//
// Возвращаемое значение:
//  Массив из Произвольный
//
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеВМассиве(Значение)
	
	Массив = Новый Массив;
	Массив.Добавить(Значение);
	
	Возврат Массив;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Функция НовыйУникальныйИдентификатор(УникальныйИдентификатор = Неопределено)
	
	Если ТипЗнч(УникальныйИдентификатор) = Тип("Строка") Тогда	
		Попытка
			Возврат Новый УникальныйИдентификатор(УникальныйИдентификатор);
		Исключение
			Возврат Новый УникальныйИдентификатор();
		КонецПопытки;
	ИначеЕсли ТипЗнч(УникальныйИдентификатор) = Тип("УникальныйИдентификатор") Тогда
		Возврат УникальныйИдентификатор;
	Иначе
		Возврат Новый УникальныйИдентификатор();
	КонецЕсли;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
// Возвращает значение в виде XML-строки.
// Преобразованы в XML-строку (сериализованы) могут быть только те объекты, 
// для которых в описании указано, что они сериализуются.
//
// Параметры:
//   Значение - Произвольный. Значение, которое необходимо сериализовать в XML-строку.
//
// Возвращаемое значение:
//   Строка - XML-строка представления значения в сериализованном виде.
//
Функция ЗначениеВСтрокуXML(Значение)
    
    СтрокаXML   = "";
    
    #Если ВебКлиент Тогда
        СтрокаXML = ЗначениеВСтрокуXMLСервер(Значение);
    #Иначе
        ЗаписьXML = Новый ЗаписьXML;
        ЗаписьXML.УстановитьСтроку();
        СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Значение, НазначениеТипаXML.Явное);
        СтрокаXML = ЗаписьXML.Закрыть();
    #КонецЕсли
    
    Возврат СтрокаXML;
    
КонецФункции

&НаСервереБезКонтекста
// Возвращает значение в виде XML-строки.
// Преобразованы в XML-строку (сериализованы) могут быть только те объекты, 
// для которых в описании указано, что они сериализуются.
//
// Параметры:
//   Значение - Произвольный. Значение, которое необходимо сериализовать в XML-строку.
//
// Возвращаемое значение:
//   Строка - XML-строка представления значения в сериализованном виде.
//
Функция ЗначениеВСтрокуXMLСервер(Значение)
	
	Возврат ЗначениеВСтрокуXML(Значение);
	
КонецФункции


&НаКлиентеНаСервереБезКонтекста
Функция НайтиСтрокуЭлементаФормы(Форма, ИмяЭлемента, КоллекцияСтрок = Неопределено)
	
	Если КоллекцияСтрок = Неопределено Тогда
		КоллекцияСтрок = Форма.Элементы.ОткрытыеФормы.ТекущиеДанные.Элементы;
	КонецЕсли;	
	
	НайденноеОписаниеЭлемента = Неопределено;
	
	Для Каждого ТекущееОписаниеЭлемента Из КоллекцияСтрок.ПолучитьЭлементы() Цикл
		
		Если ТекущееОписаниеЭлемента.Имя = ИмяЭлемента Тогда
			НайденноеОписаниеЭлемента = ТекущееОписаниеЭлемента;
		Иначе
			НайденноеОписаниеЭлемента = НайтиСтрокуЭлементаФормы(Форма, ИмяЭлемента, ТекущееОписаниеЭлемента);
		КонецЕсли;
		
		Если НЕ НайденноеОписаниеЭлемента = Неопределено Тогда
			Возврат НайденноеОписаниеЭлемента;
		КонецЕсли;
		
	КонецЦикла;
	
КонецФункции

// Определяет принадлежность объекта метаданных к ссылочному типу.
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект ссылочного типа.
//
&НаСервереБезКонтекста
Функция ЭтоОбъектСсылочногоТипа(ОбъектМетаданных)
	
	ИмяОбъектаМетаданных = ОбъектМетаданных.ПолноеИмя();
	Позиция = СтрНайти(ИмяОбъектаМетаданных, ".");
	Если Позиция > 0 Тогда 
		ИмяБазовогоТипа = Лев(ИмяОбъектаМетаданных, Позиция - 1);
		Возврат ИмяБазовогоТипа = "Справочник"
			Или ИмяБазовогоТипа = "Документ"
			Или ИмяБазовогоТипа = "БизнесПроцесс"
			Или ИмяБазовогоТипа = "Задача"
			Или ИмяБазовогоТипа = "ПланСчетов"
			Или ИмяБазовогоТипа = "ПланОбмена"
			Или ИмяБазовогоТипа = "ПланВидовХарактеристик"
			Или ИмяБазовогоТипа = "ПланВидовРасчета";
	Иначе
		Возврат Ложь;
	КонецЕсли;
	
КонецФункции
	
#КонецОбласти

#Область CollectionMethodsOneS

// Устанавливает свойство объекта по его полному пути (с учетом подчиненных свойств).
// Источник: https://github.com/SeiOkami/CollectionMethodsOneS/issues/142
// 
// Параметры:
//  Объект - Произвольный - Любой объект, который имеет какие-то свойства
//  ПутьКСвойству - Строка - Полный путь к свойству
//  Значение - Произвольный - Устанавливаемое значение
//  
// Пример:
//	УстановитьСвойствоОбъекта(Объект, "Свойство.ПодчиненноеСвойство.ЕщеПодчиненное", Значение); 
//  
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьСвойствоОбъекта(Знач Объект, Знач ПутьКСвойству, Знач Значение)
	
	ЧастиПути = СтрРазделить(ПутьКСвойству, ".");
	ИндексГраницы = ЧастиПути.ВГраница();
	ТекущийОбъект = Объект;
	
	Для Индекс = 0 По ИндексГраницы - 1 Цикл
		ТекущийОбъект = ТекущийОбъект[ЧастиПути[Индекс]]; //Произвольный
	КонецЦикла;
	
	ТекущийОбъект[ЧастиПути[ИндексГраницы]] = Значение;
	
КонецПроцедуры

#КонецОбласти

#КонецОбласти
